← Overview

offCanvasNav

Burger menu that slides the site navigation in over the page — built on the native <dialog>, and a plain block in the page without JavaScript.

The navigation is in the page, not in a widget. It is authored inside a <dialog>, and the stylesheet renders that as an ordinary block until the module has taken over — so without JavaScript, and above the navigation breakpoint, the full navigation simply sits in the header. Below the breakpoint the same markup becomes a drawer that showModal() opens in the top layer.

▸ This viewport is at or above the navigation breakpoint (--bp-navigation, 1250px): the second example below shows its navigation in the flow and hides its burger. The first one carries data-offcanvasnav-always, so it stays a drawer here.

▾ This viewport is below the navigation breakpoint (--bp-navigation, 1250px): both examples below are drawers. Widen the window past 1250px and the second one hands its navigation back to the page.

The drawer (data-offcanvasnav-always)

Open it and try everything the platform gives you for free: Tab cycles inside the drawer and cannot leave it, Esc closes it, and the focus returns to the burger afterwards. The page behind is inert and cannot be scrolled. A press beside the panel closes it too — that part is the module's, and it needs no coordinate math: the <dialog> is a transparent box over the whole viewport, so a click on it can only have landed next to the panel.

Acme Menu

Every link in there points at a target on this page, so activating one closes the drawer: a menu left standing would cover the very place the reader just jumped to. The last entry points at another site instead and is left alone — there the browser replaces the page anyway. The submenu buttons are dropdownNav's and are not links at all, so they only unfold their panel.

Breakpoint-scoped (the default)

The same component without data-offcanvasnav-always. Above --bp-navigation its burger is hidden and the navigation is rendered in the flow — the header below then shows the menu itself. Resize this window across 1250px to watch it change sides; with the drawer open, crossing the breakpoint closes it, because from there up the page shows the navigation anyway.

This one comes in from the other edge (data-offcanvasnav-side="end") — style only: the panel is anchored with a logical inset, so the side is one declaration rather than two rules. The frame below has a viewport of its own, so it shows the drawer state of this variant however wide this window happens to be.

Without JavaScript (the base layer)

This drawer carries no data-js-behavior, so the module never touches it — exactly what every visitor sees with JavaScript off, and what everyone sees for the moment before the chunk has loaded. The <dialog> is rendered as the block it is: the navigation complete and visible, its own header (title and close control) left out, because a close control with nothing to close would be a dead control. The burger next to the brand is a plain link to that navigation, and it does exactly that.

The in-page target

The links in the drawers above point here. Activating one closes the drawer and lets the browser do the jumping — the module only gets out of the way, it never scrolls anything itself. Because the fragment resolves to this heading, the browser also makes it the sequential focus navigation starting point, so the next Tab continues here rather than back at the burger.