Navigation

Four patterns. No classes. Active state via aria-current="page".

ASW provides four navigation patterns through semantic HTML and data attributes. Each renders correctly with zero custom classes — structure implies style. Active states are expressed with aria-current="page", which doubles as an accessibility signal and a CSS hook.


Top nav

The persistent bar at the top of every page. A bare <nav> direct child of <body> — no wrapper, no class, no extra divs.

The pattern is two <ul> lists: one on the left (brand), one on the right (links). Items are separated by | pipe dividers rendered via CSS — remove one item and the pipe disappears automatically.

<nav>
  <ul><li><a href="/"><strong>Brand</strong></a></li></ul>
  <ul>
    <li><a href="/asw/docs/">Docs</a></li>
    <li><a href="/asw/lab/" aria-current="page">Lab</a></li>
    <li><a href="/source" data-text="dim">Source</a></li>
  </ul>
</nav>

The nav you see at the top of this page is a live demo.

Responsive behaviour

At medium widths the link list wraps. At narrow widths the brand stacks above the links. No JavaScript required.

Dropdown

A <details> element inside a list item becomes a dropdown. No JavaScript. Closes on outside click via :focus-within CSS. The summary acts as the trigger; the inner <ul> floats below.

<nav>
  <ul><li><a href="/"><strong>Brand</strong></a></li></ul>
  <ul>
    <li><a href="/asw/docs/">Docs</a></li>
    <li>
      <details>
        <summary>More</summary>
        <ul>
          <li><a href="/about/">About</a></li>
          <li><a href="/contact/">Contact</a></li>
        </ul>
      </details>
    </li>
  </ul>
</nav>

Live demo (opens below the brand bar):




Table of contents nav

An in-page TOC for the right column of a data-layout="docs" page. Compact, small-text, with a left border active state. Designed to be read at a glance while the main content holds focus.

Pairs with toc-spy.js — a minimal scroll-observer that sets aria-current on the link matching the currently visible heading. Without the script, static active state still works via aria-current="page" set in HTML.

<aside data-toc>
  <nav aria-label="On this page" data-nav="toc">
    <small>On this page</small>
    <ul>
      <li><a href="#top-nav">Top nav</a></li>
      <li><a href="#subnav">Sub-navigation</a></li>
      <li><a href="#sidebar-nav">Sidebar nav</a></li>
      <li><a href="#toc-nav" aria-current="true">Table of contents</a></li>
    </ul>
  </nav>
</aside>

The TOC to the right of this page is a live demo, including the scroll-spy active state.

toc-spy.js

Include the script at the bottom of the page. It observes h2[id] and h3[id] headings inside <article> and updates aria-current on scroll using IntersectionObserver. No dependencies.

<script src="../toc-spy.js"></script>

Active state — aria-current

All ASW nav patterns use aria-current for active state. No .active class, no data-active, no JavaScript required for static pages. The attribute communicates intent to both the CSS and to assistive technology.

Pattern Attribute Visual effect
Top nav aria-current="page" Full-brightness text (vs dimmed inactive)
Sub-navigation aria-current="page" Full-brightness text
Sidebar nav aria-current="page" Accent colour background + accent text
TOC nav aria-current="true" (set by scroll-spy) Accent text + left border in accent colour

Use aria-current="page" for links that represent the current page. Use aria-current="true" (or any value) for the scroll-spy's dynamic active state — the scroll position isn't a "page" but the attribute still carries meaning.