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

Page Navigation

Prev and next across an ordered sequence of pages

Website / Page Navigation
Download .md file
Open .md in new tab
On this page
  • Anatomy
  • Basic usage
  • The section line
  • Ends of the sequence
  • Responsive
  • Accessibility
  • Usage rules
  • CSS reference
  • Use in another product

Page navigation is the pager at the foot of a page: previous on the left, next on the right. It works across any ordered sequence and knows nothing about what the sequence is — pair it with Book for a documentation space, or with anything else that has an order. The class is required, and data-direction chooses the side.

It is the sideways move in a three-part model. Down is Book — shelf to cover to contents. Up is Breadcrumb. Sideways is this.


Anatomy

nav.page-nav
  .page-nav-inner
    a.page-nav-link          data-direction="prev"
      .svg-icn.page-nav-arrow
      .page-nav-text
        .page-nav-label      ← "Previous" / "Next"
        .page-nav-section    ← only when the neighbour is in another section
        .page-nav-title      ← the target page's name
    a.page-nav-link          data-direction="next"
      …

Both directions render from identical markup — the arrow always comes first in the DOM. data-direction="next" reverses the row in CSS, so this is one component with a variant rather than two that happen to share class names.

The title is a <span>, not a heading. It labels a link; it does not open a section. Two <h3>s in the page footer would put phantom entries in the document outline that screen-reader users navigate by.


Basic usage

Both halves filled — the reader is mid-sequence.

Previous 4.4 Iconography
Next 4.6 Motion

Note the arrow is written first inside both links. The next link only looks reversed — data-direction="next" flips the row in CSS. Narrow the window and watch the two halves stack; the chevron stays on the right where it belongs.

<nav class="page-nav" aria-label="Page navigation">
  <div class="page-nav-inner">
    <a href="/brand/iconography.html" class="page-nav-link" data-direction="prev" rel="prev">
      <div class="svg-icn page-nav-arrow"><!-- chevron-left-large --></div>
      <span class="page-nav-text">
        <span class="page-nav-label">Previous</span>
        <span class="page-nav-title">4.4 Iconography</span>
      </span>
    </a>
    <a href="/brand/tone-of-voice.html" class="page-nav-link" data-direction="next" rel="next">
      <div class="svg-icn page-nav-arrow"><!-- chevron-right-large --></div>
      <span class="page-nav-text">
        <span class="page-nav-label">Next</span>
        <span class="page-nav-title">4.6 Motion</span>
      </span>
    </a>
  </div>
</nav>

Note the arrow comes first in both links. Do not reorder it for the next direction — the CSS handles that, and moving it breaks the shared shape.

rel="prev" and rel="next" describe the sequence to browsers and crawlers. Keep them.


The section line

appears only when the neighbour sits in a different section. It marks the moment you leave one book for the next, which is the point at which the destination needs naming.

Showing it on every link would turn a signpost into chrome — on a page whose neighbour is in the same section, repeating that section's name tells the reader nothing they don't already know.

Here the reader is on the last page of the Brand Book. Previous stays inside the book and says nothing extra; next names where it is about to take them.

Previous 4.6 Motion
Next Design System Introduction
<span class="page-nav-text">
  <span class="page-nav-label">Next</span>
  <span class="page-nav-section">Design System</span>
  <span class="page-nav-title">Introduction</span>
</span>

Only render the element when it has content. An empty <span class="page-nav-section"></span> still draws a gap inside the column, because is a flex container with a row gap.


Ends of the sequence

When there is no neighbour in a direction, render nothing for that side. Do not emit a hidden placeholder: grid-column pins each link to its own half, so the surviving link keeps its side on its own.

First page in the sequence — next only, still sitting on the right:

Next 1.2 Our Values

Last page — previous only, on the left:

Previous 6.4 Project Setup
<!-- first page in the sequence: next only, still on the right -->
<nav class="page-nav" aria-label="Page navigation">
  <div class="page-nav-inner">
    <a href="…" class="page-nav-link" data-direction="next" rel="next">…</a>
  </div>
</nav>

If both neighbours are missing, render no <nav> at all rather than an empty one.


Responsive

Below 768px the two halves collapse into a single column and stack — previous above next — with a rule between them. The breakpoint belongs to the component rather than a shared responsive section, so it travels into another product with the rest of the CSS.

The title also steps down a size below 960px, matching the heading scale. That step is carried by --page-nav-title-size, so re-pointing the token changes both sizes from one place.


Accessibility

  • Label the landmark. <nav> needs aria-label="Page navigation", so a screen-reader user moving by landmark can tell it apart from the site's main navigation.
  • The title is a <span>, deliberately. Using a heading here injects entries into the document outline at the foot of every page, which is misleading when navigating by heading.
  • The arrow is decorative and must carry aria-hidden="true". It repeats the direction the label already states. Icons rendered through the wrapper already do this.
  • The accessible name is the whole link text — "Next", the section if present, and the title. That reads well and satisfies SC 2.4.4 Link Purpose. Do not add an aria-label that drops the title.
  • rel="prev" / rel="next" describe the sequence programmatically. They are not a substitute for the visible label.
  • Reversing the row does not affect the tab order. Each link is a single tab stop, and the reversal is visual only.

Usage rules

Do:

  • Keep the arrow first in the DOM for both directions and let data-direction do the flipping
  • Render the section line only when the neighbour is in a different section, and only when it has content
  • Omit the whole link when there is no neighbour in that direction
  • Re-point tokens to restyle — a product changes --page-nav-link-padding, not the rule

Don't:

  • Don't use a heading element for
  • Don't emit a hidden placeholder to hold an empty column; grid-column already does
  • Don't add or a container class to — the links carry their own inset
  • Don't confuse with the sidebar's ; they are unrelated components
  • Don't reach for this when the set has no meaningful order — a pager implies a sequence a reader can follow

CSS reference

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

Tokens

Token Default What it controls
Link fill
Link fill on hover
var(--border-s) solid var(--border-faded) Top rule, and the divider between stacked links on mobile
var(--space-xl) var(--space-2xl) Inset inside each half
Space between arrow and text
Title size; steps to below 960px
Arrow at rest
Arrow on hover

Selectors

Selector Purpose
Landmark wrapper; declares the component tokens and the top rule
Two-column grid, no gutter
One direction — the whole half is the link
.page-nav-link[data-direction="prev"] Pinned to column 1
.page-nav-link[data-direction="next"] Pinned to column 2, row reversed, right aligned
Direction chevron; decorative
Label, section, and title stacked
Eyebrow naming the relationship
Target's section — only when crossing
Target page name, clamped to two lines

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
  • The section line
  • Ends of the sequence
  • Responsive
  • Accessibility
  • Usage rules
  • CSS reference
  • Use in another product
Previous Book
Next Nav

Was this page helpful?

We use this feedback to improve our documentation.

Thanks for your feedback

Send feedback

© 2026 By Default