← Component Library
Navigation Components

Navigation Patterns

The ways people move through a site — menus, breadcrumbs, pagination, steppers, and more. Each pattern has a live demo and the HTML & CSS behind it.

01 · Mega Menu

A wide, multi-column dropdown

When a site has lots of sections, a mega menu shows them in organized columns under one nav item. Hover (or focus) the button to open it.

Hover “Products” to reveal the columns.

HTML

<nav class="mega">
  <button class="trigger">Products ▾</button>
  <div class="panel">
    <div>
      <h5>Build</h5>
      <a href="#">Editor</a>
      <a href="#">Templates</a>
      <a href="#">Components</a>
    </div>
    <div>
      <h5>Learn</h5>
      <a href="#">Guides</a>
      <a href="#">Tutorials</a>
      <a href="#">Examples</a>
    </div>
    <div>
      <h5>Ship</h5>
      <a href="#">Hosting</a>
      <a href="#">Domains</a>
      <a href="#">Analytics</a>
    </div>
  </div>
</nav>

CSS

.mega { position: relative; display: inline-block; }
.mega .panel {
  position: absolute; top: 100%; left: 0;
  margin-top: 8px;
  display: none;
  grid-template-columns: repeat(3, minmax(96px, 1fr));
  gap: 16px;
  min-width: 340px;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  padding: 16px;
  box-shadow: 0 12px 30px rgba(0,0,0,.12);
}
.mega:hover .panel,
.mega:focus-within .panel { display: grid; }
.mega h5 { font-size: .68rem; text-transform: uppercase; color: #9aa3b2; margin-bottom: 6px; }
.mega a { display: block; color: #374151; text-decoration: none; font-size: .82rem; padding: 3px 0; }
Add keyboard + screen-reader support (e.g., aria-expanded and a JS toggle) for production — hover alone isn't accessible to everyone.
04 · Pagination

Split content across pages

Numbered controls for moving through long lists of results or posts. Mark the current page so it stands out.

HTML

<nav aria-label="Pagination">
  <a href="#">«</a>
  <a href="#">1</a>
  <a href="#" aria-current="page">2</a>
  <a href="#">3</a>
  <a href="#">4</a>
  <a href="#">»</a>
</nav>

CSS

nav a {
  min-width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid #e5e7eb; border-radius: 8px;
}
nav a[aria-current="page"] {
  background: #38bdf8; color: #fff; border-color: #38bdf8;
}
05 · Back to Top

Jump back to the top

A button that returns the user to the top of a long page. The simplest version is a link to a top anchor with smooth scrolling — no JavaScript needed.

Back to top

In a real page this sits fixed in the bottom-right corner.

HTML

<a href="#top" class="back-to-top">↑ Back to top</a>

CSS

html { scroll-behavior: smooth; }   /* animate the jump */

.back-to-top {
  position: fixed;
  bottom: 24px; right: 24px;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 18px;
  border-radius: 999px;
  background: #0b1a33; color: #fff;
  text-decoration: none;
  font-weight: 600; font-size: .85rem;
}
To show it only after the user scrolls down, toggle a class with a few lines of JavaScript on the scroll event.
06 · Off-Canvas Menu

Slide a panel in from the edge

A menu that lives off-screen and slides in — common on mobile. This pure-CSS version uses a hidden checkbox as the toggle. Click “Menu” in the demo.

Page content — click “Menu” to slide the panel in.

HTML

<input type="checkbox" id="oc">
<label class="open" for="oc">☰ Menu</label>
<nav class="panel">
  <label class="close" for="oc">×</label>
  <a href="#">Home</a>
  <a href="#">Docs</a>
  <a href="#">Pricing</a>
  <a href="#">Contact</a>
</nav>

CSS

.panel {
  position: fixed; top: 0; left: 0; height: 100%;
  width: 260px;
  transform: translateX(-100%);   /* hidden off-screen */
  transition: transform .3s ease;
}
#oc { display: none; }
#oc:checked ~ .panel { transform: translateX(0); }  /* slide in */
07 · Wizard Navigation

Show progress through steps

A horizontal progress indicator for multi-step flows (checkout, onboarding). Mark completed, current, and upcoming steps differently.

Account
Profile
3
Payment
4
Done

HTML

<ol class="wizard">
  <li class="done"><span class="dot">✓</span>Account</li>
  <li class="done"><span class="dot">✓</span>Profile</li>
  <li class="active" aria-current="step"><span class="dot">3</span>Payment</li>
  <li><span class="dot">4</span>Done</li>
</ol>

CSS

.wizard { display: flex; list-style: none; }
.wizard li { flex: 1; text-align: center; }
.wizard .dot {
  width: 30px; height: 30px; border-radius: 50%;
  background: #e5e7eb; margin: 0 auto 6px;
}
.wizard .done .dot   { background: #22c55e; color: #fff; }
.wizard .active .dot { background: #38bdf8; color: #fff; }
08 · Step Navigation

A vertical numbered stepper

Lay out a sequence of steps with a connecting line — great for tutorials, recipes, or setup guides where order matters.

  1. Install the editor

    Download and open VS Code.

  2. 2
    Create your project

    Open a folder and add index.html.

  3. 3
    Publish it

    Push to GitHub Pages.

HTML

<ol class="steps">
  <li class="done"><span class="num">✓</span>
    <div><h5>Install the editor</h5><p>Download and open VS Code.</p></div></li>
  <li class="active"><span class="num">2</span>
    <div><h5>Create your project</h5><p>Open a folder and add index.html.</p></div></li>
  <li><span class="num">3</span>
    <div><h5>Publish it</h5><p>Push to GitHub Pages.</p></div></li>
</ol>

CSS

.steps { list-style: none; }
.steps li { display: flex; gap: 12px; padding-bottom: 18px; position: relative; }
.steps li::before {            /* the connecting line */
  content: ""; position: absolute; left: 14px; top: 32px; bottom: -2px;
  width: 2px; background: #e5e7eb;
}
.steps .num {
  width: 30px; height: 30px; border-radius: 50%;
  background: #e5e7eb; display: flex; align-items: center; justify-content: center;
}
.steps .done .num   { background: #22c55e; color: #fff; }
.steps .active .num { background: #38bdf8; color: #fff; }
09 · Vertical Navigation

A stacked side menu

Navigation laid out as a vertical column — common for dashboards, docs sidebars, and settings. Stack the links and highlight the current one.

The selected page's content appears here.

HTML

<nav class="sidebar-nav">
  <a href="#" class="active">Dashboard</a>
  <a href="#">Reports</a>
  <a href="#">Team</a>
  <a href="#">Settings</a>
</nav>

CSS

.sidebar-nav {
  display: flex;
  flex-direction: column;   /* stack vertically */
  gap: 4px;
}
.sidebar-nav a { padding: 9px 12px; border-radius: 8px; text-decoration: none; }
.sidebar-nav a.active { background: #e0f2fe; color: #0369a1; font-weight: 700; }
10 · Scroll Navigation

Highlight the section you're in (scroll-spy)

Scroll navigation tracks the page as you scroll and highlights the matching link — common in docs and long pages. Scroll the box and watch the side links update. (This is different from scrollytelling, which animates content as you scroll.)

Intro

Scroll down inside this box…

Features

…the active link follows along…

Pricing

…until you reach the end.

HTML

<nav class="spy">
  <a href="#intro" class="active">Intro</a>
  <a href="#features">Features</a>
  <a href="#pricing">Pricing</a>
</nav>
<section id="intro"><h5>Intro</h5><p>Scroll down inside this box…</p></section>
<section id="features"><h5>Features</h5><p>…the active link follows along…</p></section>
<section id="pricing"><h5>Pricing</h5><p>…until you reach the end.</p></section>

CSS

.spy a.active { background: #e0f2fe; color: #0369a1; font-weight: 700; }

JavaScript — the scroll-spy

const links = document.querySelectorAll('.spy a');
const map = {}; links.forEach(a => map[a.getAttribute('href').slice(1)] = a);
const observer = new IntersectionObserver(entries => {
  entries.forEach(e => {
    if (e.isIntersecting) {
      links.forEach(a => a.classList.remove('active'));
      map[e.target.id].classList.add('active');
    }
  });
}, { rootMargin: '-10% 0px -60% 0px' });
document.querySelectorAll('section').forEach(sec => observer.observe(sec));
12 · Responsive Navigation

One nav that adapts to any screen

On wide screens the links sit in a row; on narrow screens they collapse behind a “hamburger” button. This demo uses the pure-CSS checkbox hack — no JavaScript. Tap the ☰ button to open and close the menu.

HTML — checkbox toggles the menu

<input type="checkbox" id="nav-toggle" class="nav-check">
<nav>
  <span class="brand">Studio</span>
  <label for="nav-toggle" class="burger">☰</label>
  <ul class="links">
    <li><a href="#">Home</a></li>
    <li><a href="#">Work</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>

CSS — collapse on small screens, row on large

.links { max-height: 0; overflow: hidden; transition: max-height .25s; }  /* collapsed */
.nav-check:checked ~ nav .links { max-height: 260px; }                   /* opened */

@media (min-width: 700px) {     /* wide screens: show links inline, hide burger */
  .burger { display: none; }
  .links  { display: flex; max-height: none; width: auto; }
}
The checkbox hack keeps this working even with JavaScript disabled. For animated icons or closing on outside-click, a few lines of JS can enhance it — see Mobile Navigation.
13 · Full Page

The whole thing as one file

Several of these patterns — a responsive navbar with a hamburger, breadcrumbs, pagination, and a back-to-top link — combined into one complete HTML file. Copy it into a new file called index.html, open it in a browser, and it just works — no libraries, no build step. Here's the live result, then the full code.

Live preview

Complete HTML — copy this whole file

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Navigation Patterns Demo</title>
  <style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    html { scroll-behavior: smooth; }
    body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #1f2433; background: #f6f7fb; }

    /* ===== Responsive navbar ===== */
    .navbar {
      display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
      padding: 14px 24px; background: #fff; border-bottom: 1px solid #e9edf3;
      position: sticky; top: 0; z-index: 100;
    }
    .navbar .brand { font-weight: 800; font-size: 1.15rem; color: #111; text-decoration: none; }
    .navbar .burger {
      margin-left: auto; width: 40px; height: 40px; font-size: 1.4rem;
      background: none; border: 1px solid #cbd5e1; border-radius: 8px;
      color: #111; cursor: pointer;
    }
    .navbar .links { display: flex; gap: 20px; align-items: center; list-style: none; }
    .navbar .links a { color: #4b5563; text-decoration: none; font-size: .95rem; }
    .navbar .links a:hover, .navbar .links a.active { color: #2563eb; }

    /* ===== Page layout ===== */
    main { max-width: 760px; margin: 0 auto; padding: 24px; }

    /* ===== Breadcrumbs ===== */
    .breadcrumb { display: flex; gap: 8px; align-items: center; font-size: .9rem; color: #6b7280; margin-bottom: 18px; flex-wrap: wrap; }
    .breadcrumb a { color: #2563eb; text-decoration: none; }
    .breadcrumb .sep { color: #cbd5e1; }
    .breadcrumb [aria-current="page"] { color: #111; font-weight: 600; }

    .card { background: #fff; border: 1px solid #e9edf3; border-radius: 12px; padding: 24px; margin-bottom: 18px; }
    .card h1 { font-size: 1.8rem; margin-bottom: 10px; }
    .card p { color: #4b5563; margin-bottom: 12px; }

    /* ===== Pagination ===== */
    .pagination { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; margin: 8px 0 28px; }
    .pagination a {
      min-width: 38px; height: 38px; display: inline-flex; align-items: center; justify-content: center;
      border: 1px solid #e5e7eb; border-radius: 8px; color: #374151; text-decoration: none; font-size: .9rem;
    }
    .pagination a:hover { border-color: #2563eb; }
    .pagination a[aria-current="page"] { background: #2563eb; color: #fff; border-color: #2563eb; }

    /* ===== Back to top ===== */
    .back-to-top {
      position: fixed; bottom: 24px; right: 24px;
      padding: 11px 18px; border-radius: 999px;
      background: #0b1a33; color: #fff; text-decoration: none;
      font-weight: 600; font-size: .85rem; box-shadow: 0 8px 20px rgba(0,0,0,.18);
    }

    /* ===== Mobile: collapse links behind the burger ===== */
    @media (max-width: 640px) {
      .navbar .links {
        display: none; width: 100%; flex-direction: column;
        align-items: flex-start; gap: 6px; padding-top: 10px;
      }
      .navbar .links.open { display: flex; }
    }
    @media (min-width: 641px) {
      .navbar .burger { display: none; }
    }
  </style>
</head>
<body id="top">

  <header class="navbar">
    <a class="brand" href="index.html">Studio</a>
    <button class="burger" aria-label="Toggle menu" aria-expanded="false">&#9776;</button>
    <ul class="links">
      <li><a href="#" class="active">Home</a></li>
      <li><a href="#">Work</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Contact</a></li>
    </ul>
  </header>

  <main>
    <nav class="breadcrumb" aria-label="Breadcrumb">
      <a href="#">Home</a><span class="sep">/</span>
      <a href="#">Blog</a><span class="sep">/</span>
      <span aria-current="page">Navigation Patterns</span>
    </nav>

    <article class="card">
      <h1>Navigation Patterns</h1>
      <p>This page wires together four common navigation pieces: a responsive
        navbar that collapses behind a hamburger on small screens, breadcrumbs
        that show where you are, numbered pagination, and a back-to-top link.</p>
      <p>Make the window narrow and the links collapse into the &#9776; button.
        Scroll down and the back-to-top link returns you here with a smooth jump.</p>
      <p style="height: 360px;">Plenty of room to scroll…</p>
    </article>

    <nav class="pagination" aria-label="Pagination">
      <a href="#top">&laquo;</a>
      <a href="#top">1</a>
      <a href="#top" aria-current="page">2</a>
      <a href="#top">3</a>
      <a href="#top">4</a>
      <a href="#top">&raquo;</a>
    </nav>
  </main>

  <a class="back-to-top" href="#top">&uarr; Top</a>

  <script>
    const burger = document.querySelector('.navbar .burger');
    const links = document.querySelector('.navbar .links');
    burger.addEventListener('click', () => {
      const open = links.classList.toggle('open');
      burger.setAttribute('aria-expanded', open);
    });
  </script>
</body>
</html>
That's a real, standalone page. The live preview above is rendered from the exact code in the box — so what you copy is precisely what you see.
13 · Related

Keep building

See Navigation for nav bars, Mobile Navigation for the hamburger pattern, Tabs, and the Header — or browse the full Component Library.