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 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.
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.