Nav Collapse
Mobile menu for Navbar. Prefer native <details> — open and close with no JavaScript. The default panel is a surface under the trigger; inside a navbar it becomes a full-width sheet under the bar. af-is-overlay is the full-page variant.
Menu
<details class="af-nav-collapse">
<summary class="af-btn af-is-sm">Menu</summary>
<nav aria-label="Site">
<ul>
<li>
<a href="#" aria-current="page">Home</a>
</li>
<li>
<a href="#">Docs</a>
</li>
<li>
<a href="#">Blog</a>
</li>
</ul>
</nav>
</details>In a navbar
Section titled “In a navbar”Put the toggle in af-navbar-actions. Below md (768px), af-navbar-nav hides when a collapse is present. af-is-compact forces that chrome at any width — use it for demos, or for an always-hamburger header.
<nav class="af-navbar af-is-compact">
<a href="#" class="af-navbar-brand">Brand</a>
<ul class="af-navbar-nav">
<li>
<a href="#">Home</a>
</li>
<li>
<a href="#">Docs</a>
</li>
</ul>
<div class="af-navbar-actions">
<details class="af-nav-collapse">
<summary class="af-btn af-is-sm">Menu</summary>
<nav aria-label="Site">
<ul>
<li>
<a href="#" aria-current="page">Home</a>
</li>
<li>
<a href="#">Docs</a>
</li>
<li>
<a href="#">Blog</a>
</li>
</ul>
</nav>
</details>
</div>
</nav>Markup
Section titled “Markup”Open with the open attribute (or .af-nav-collapse-open on the menu for the button path). summary takes af-btn so it matches other controls; the native disclosure marker is removed.
Button and JavaScript
Section titled “Button and JavaScript”If you cannot use <details>, a <button> plus your own toggle still works. You own ARIA, focus, and Escape:
<div class="af-nav-collapse" open>
<button
type="button"
class="af-btn af-is-sm"
aria-expanded="true"
aria-controls="nav-menu"
>Menu</button>
<nav id="nav-menu">
<ul>
<li>
<a href="#" aria-current="page">Home</a>
</li>
<li>
<a href="#">Docs</a>
</li>
</ul>
</nav>
</div>Toggle open on the container, or hidden / .af-nav-collapse-open on the menu. Focus trap, Escape, and return-focus are not in the CSS.
Overlay
Section titled “Overlay”af-is-overlay fills the viewport below the bar — a full-page mobile menu, not a dropdown sheet. Pair it with a sticky or fixed navbar. Set --af-navbar-height on the bar to the real height (default 3.5rem). Overlay open locks document scroll in CSS. Close <details> on navigate. Focus trap stays in your script.
<!-- Required: --af-navbar-height must match the real bar (default 3.5rem). Close this details on route change. -->
<nav class="af-navbar af-is-compact" style="--af-navbar-height: 3.5rem">
<a href="#" class="af-navbar-brand">Brand</a>
<ul class="af-navbar-nav">
<li>
<a href="#">Home</a>
</li>
<li>
<a href="#">Docs</a>
</li>
</ul>
<div class="af-navbar-actions">
<details class="af-nav-collapse af-is-overlay">
<summary class="af-btn af-is-sm">Menu</summary>
<nav aria-label="Site">
<ul>
<li>
<a href="#" aria-current="page">Home</a>
</li>
<li>
<a href="#">Docs</a>
</li>
<li>
<a href="#">Blog</a>
</li>
</ul>
<div class="af-nav-collapse-cta">
<a href="#" class="af-btn af-w-full">Get Started</a>
</div>
</nav>
</details>
</div>
</nav>CSS classes
Section titled “CSS classes”.af-nav-collapse— container (<details>or a<div>).af-nav-collapse-open— show the menu (on the<nav>/<ul>).af-nav-collapse-menu— optional class on the menu panel.af-nav-collapse.af-is-overlay— full-page panel below--af-navbar-height. Open overlay locks document scroll..af-nav-collapse-cta— optional pinned action in the overlay.af-navbar.af-is-compact— always hide inline nav and show the collapse
Required ARIA (button path)
Section titled “Required ARIA (button path)”aria-expandedon the triggeraria-controlslinking trigger to menuhiddenon the menu when closed
SPA hosts
Section titled “SPA hosts”Close <details> on route change. Overlay open already locks document scroll in CSS. Focus trap stays in the app.
Related
Section titled “Related”- Navbar — below
md,af-navbar-navhides when anaf-nav-collapseis present. Put the toggle inaf-navbar-actions.