Navigation List

Use .nav-list for a semantic list of navigation links. It removes native list chrome but does not force a direction. Combine it with layout primitives depending on context.

<h2>Navigation</h2>
<nav aria-label="Main navigation">
  <ul class="nav-list cluster">
    <li><a href="/docs">Docs</a></li>
    <li><a href="/components">Components</a></li>
    <li><a href="/examples">Examples</a></li>
  </ul>
</nav>
<h2>Documentation</h2>
<nav aria-label="Documentation">
  <ul class="nav-list stack">
    <li><a href="/docs/getting-started" aria-current="page">Getting started</a></li>
    <li><a href="/docs/tokens">Tokens</a></li>
    <li><a href="/docs/layout">Layout</a></li>
    <li><a href="/docs/components">Components</a></li>
  </ul>
</nav>

Use .nav-list for:

  • header navigation
  • side navigation
  • footer navigation
  • tab-like navigation lists
  • documentation navigation

Do not reset every list inside nav.

CSS

/* Avoid */
nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

This is too broad and removes native list behavior from every navigation context, including nested documentation trees or rich content. Prefer an explicit pattern class.

<nav aria-label="Footer">
  <ul class="nav-list cluster">
    <li><a href="/privacy">Privacy</a></li>
    <li><a href="/terms">Terms</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

Header Navigation

Header navigation is usually a composition of landmarks, layout primitives, and patterns.

<header class="site-header">
  <div class="center cluster" style="--cluster-justify: space-between">
    <a class="brand" href="/">Actual CSS</a>

    <nav aria-label="Main navigation">
      <ul class="nav-list cluster">
        <li><a href="/docs">Docs</a></li>
        <li><a href="/components">Components</a></li>
        <li><a href="/examples">Examples</a></li>
      </ul>
    </nav>
  </div>
</header>

In this example:

  • header provides the document landmark.
  • .center constrains the content.
  • .cluster arranges the brand and navigation.
  • nav provides navigation semantics.
  • .nav-list normalizes the navigation list.
  • the inner .cluster arranges navigation items horizontally.

A project may add .site-header when it needs a visual shell.

CSS

.site-header {
  border-block-end: 1px solid var(--border);
  background: var(--surface);
}

App Shell With Sidebar

.app-shell (see Layout → Header And Footer) covers the simple case: a single column stacked header/main/footer. A persistent-sidebar app — a dashboard, an admin panel — needs a second, distinct shape: a two-column grid where the sidebar collapses below a breakpoint. These are not the same primitive solving the same problem two ways; .app-shell has no sidebar at all.

<div class="shell-sidebar">
  <aside class="shell-sidebar-nav" aria-label="Primary">
    <a class="navbar-brand" href="#"><span class="avatar primary"><abbr>AC</abbr></span> Product</a>
    <nav aria-label="Primary">
      <ul class="nav-list stack">
        <li><a class="nav-link" href="#" aria-current="page">Overview</a></li>
        <li><a class="nav-link" href="#">Settings</a></li>
      </ul>
    </nav>
  </aside>

  <div class="shell-sidebar-main">
    <header class="topbar">...</header>
    <main class="center">...</main>
  </div>
</div>

CSS

.shell-sidebar {
  display: grid;
  grid-template-columns: 1fr;
  min-block-size: var(--viewport-block);
}

.shell-sidebar-nav {
  display: none;
  flex-direction: column;
  gap: var(--gap);
  inline-size: var(--shell-sidebar-size, 16rem);
  padding: var(--space-4);
  border-inline-end: var(--border-width) solid var(--border);
  background: var(--surface-raised);
}

.shell-sidebar-main {
  min-inline-size: 0;
}

@media (min-width: 64rem) {
  .shell-sidebar {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .shell-sidebar-nav {
    display: flex;
    position: sticky;
    inset-block-start: 0;
    block-size: var(--viewport-block);
    overflow-y: auto;
  }
}

The sidebar width is the one tunable a project reaches for often, so it is exposed as --shell-sidebar-size rather than hard-coded — override it locally (style="--shell-sidebar-size: 18rem" or in a project stylesheet) instead of forking the rule. The breakpoint stays a literal 64rem in the media query: custom properties cannot be substituted into a media condition, so a project that genuinely needs a different one copies the rule rather than fighting the token. Below the breakpoint, mirror the sidebar into a .drawer (see UI → Drawer) for mobile access — the two are separate elements, not a responsive transform of one.

Side Navigation

Side navigation is usually a .nav-list composed with .stack.

<aside>
  <nav aria-label="Documentation">
    <ul class="nav-list stack">
      <li><a href="/docs/getting-started" aria-current="page">Getting started</a></li>
      <li><a href="/docs/tokens">Tokens</a></li>
      <li><a href="/docs/layout">Layout</a></li>
      <li><a href="/docs/components">Components</a></li>
    </ul>
  </nav>
</aside>

A project may add .side-nav only when it needs specific visual behavior such as indentation, sticky positioning, section labels, or active states.

<aside class="side-nav">
  <nav aria-label="Documentation">
    <ul class="nav-list stack">
      <li><a href="/docs/getting-started" aria-current="page">Getting started</a></li>
      <li><a href="/docs/tokens">Tokens</a></li>
      <li><a href="/docs/layout">Layout</a></li>
    </ul>
  </nav>
</aside>

CSS

.side-nav {
  font-size: var(--font-size-sm);
}

.side-nav a {
  color: inherit;
  text-decoration: none;
}

.side-nav a[aria-current="page"] {
  font-weight: 600;
}

Optional Navigation Link Styling

.nav-list can stay purely structural. If the framework wants navigation links to have a default hit area and active state, this can be added as a lightweight visual pattern.

CSS

.nav-list a {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: 2rem;
  padding-inline: var(--space-2);
  border-radius: var(--radius-sm);
  color: inherit;
  text-decoration: none;
}

.nav-list a:hover {
  background: var(--surface-subtle);
}

.nav-list a[aria-current="page"] {
  background: var(--surface-subtle);
  font-weight: 600;
}

Keep this separate from layout primitives. .cluster and .stack should not style links.