⚠️ Design system CSS not found. Check the path in cms/docs.config.js → designSystemPath, then re-run npm run docgen.

Nav

A flat set of navigation links

Website / Nav
Download .md file
Open .md in new tab
On this page
  • Anatomy
  • Basic usage
  • Orientation
  • Composition
  • Accessibility
  • Usage rules
  • CSS reference
  • Use in another product

Nav is a flat set of links. It appears in a Site Header, inside a nav Drawer on small screens, and in a footer — the same markup in all three, with orientation as the only difference.

It is deliberately not the docs sidebar's tree nav. That one has collapsible sections, sublists and an active trail, and is a different component that happens to also be navigation; its classes are .sidebar-nav-* and it belongs to the docs site rather than the design system. If you need a hierarchy, you do not need this.


Anatomy

nav.nav                    data-orientation="horizontal" | "vertical"
  a.nav-link               aria-current="page" on the current item

Links are direct children. There is no list wrapper: a horizontal row of five links is not a list a reader needs announced as one, and the extra element only makes the flex layout harder to reason about.


Basic usage

Work Studio Journal Contact
<nav class="nav" aria-label="Main">
  <a class="nav-link" href="/work" aria-current="page">Work</a>
  <a class="nav-link" href="/studio">Studio</a>
  <a class="nav-link" href="/journal">Journal</a>
  <a class="nav-link" href="/contact">Contact</a>
</nav>

aria-label on the <nav> is required when a page has more than one navigation landmark, which is nearly always true once there is a header and a footer.


Orientation

Horizontal is the default. Vertical is what a drawer or a footer column uses.

Work Studio Journal Contact
<nav class="nav" data-orientation="vertical" aria-label="Main">
  ...
</nav>

Horizontal links never wrap — a wrapped link inside a header changes the bar's height. Vertical links wrap freely, because a column has the width to spare.


Composition

In a site header

The nav sits between the header's start and end slots.

<header class="site-header">
  <div class="site-header-inner">
    <div class="site-header-start">
      <a class="site-header-logo" href="/">…</a>
    </div>
    <nav class="nav" aria-label="Main">
      <a class="nav-link" href="/work" aria-current="page">Work</a>
      <a class="nav-link" href="/studio">Studio</a>
    </nav>
    <div class="site-header-end">
      <button class="button header-action" data-icon-only aria-label="Account">…</button>
    </div>
  </div>
</header>

Below 768px the header hides its nav, on the assumption the same links are reachable from a drawer. If you put a nav in a header, give it a drawer too.

In a drawer

Same links, vertical, inside the drawer the header's menu button opens.

<dialog id="main-nav" class="drawer" data-placement="start" aria-label="Main navigation">
  <div class="drawer-header">
    <button class="button close-btn" data-icon-only data-size="small"
            data-drawer-close aria-label="Close navigation">…</button>
  </div>
  <div class="drawer-body">
    <nav class="nav" data-orientation="vertical" aria-label="Main">
      <a class="nav-link" href="/work" aria-current="page">Work</a>
      <a class="nav-link" href="/studio">Studio</a>
    </nav>
  </div>
</dialog>

Accessibility

Requirement How
Landmark <nav> is the element. Do not use a <div> with role="navigation" when the element exists
Multiple navs aria-label on each <nav>, so "Main" and "Footer" are distinguishable
Current page aria-current="page" on one link, and only one
Focus Inherited from the global focus rule; the component adds no ring of its own
Contrast The current-item treatment is weight plus colour, never colour alone

The current item is styled from aria-current, not a class. There is no here on purpose: with one attribute doing both jobs, the visible state and the announced state cannot drift apart. A design that highlights the current link but never tells a screen reader is a common and invisible failure.


Usage rules

Do:

  • Set aria-current="page" on exactly one link
  • Give every <nav> an aria-label when a page has more than one
  • Pair a header nav with a drawer, since the header hides it on small screens
  • Keep the set short enough to fit without wrapping — a header nav that needs to wrap is a nav that needs a drawer

Don't:

  • Don't use this for hierarchical navigation; it has no concept of a section or an active trail
  • Don't use .sidebar-nav-* classes here — those belong to the docs shell, not the design system
  • Don't mark the current item with a class instead of aria-current
  • Don't put non-navigation controls in a <nav>; a theme toggle is an action and belongs in the header's end slot

CSS reference

This section documents how the component is built. For usage, see the sections above.

Tokens

Token Default What it controls
Space between links, both orientations
var(--space-s) var(--space-m) Link hit area
Resting link colour
Hover colour
Colour of the aria-current link

Selectors

Selector Purpose
Base component, horizontal
.nav[data-orientation="vertical"] Column variant; stretches links
A link
.nav-link[aria-current="page"] Current page treatment
.nav:not([data-orientation="vertical"]) .nav-link white-space: nowrap, horizontal only

Key rules

Layout: flex, gap: var(--nav-gap). Vertical switches flex-direction to column and align-items to stretch.
Current item: colour plus font-weight: var(--font-weight-semi-bold), keyed off the ARIA attribute.
Nothing sets width, position or background — the container owns all three, which is what lets one component serve a header, a drawer and a footer.


Use in another product

The design system installs once per product:

npm install github:bydefaultstudio/design-system-dist#semver:^4.7.0

This component's styles ship in design-system.css. No JavaScript, nothing else to include.

On this page
  • Anatomy
  • Basic usage
  • Orientation
  • Composition
  • Accessibility
  • Usage rules
  • CSS reference
  • Use in another product
Previous Page Navigation
Next Site Header

Was this page helpful?

We use this feedback to improve our documentation.

Thanks for your feedback

Send feedback

© 2026 By Default