Navbar
The header of a site: brand, links, actions and, on narrow screens, a panel that folds. The server sends it working — above the collapse breakpoint it is a bar, below it the panel is served open and stacked under the brand, so no link is ever out of reach. On init the burger appears, the panel folds, Escape and a click outside close it, and a sticky header condenses once the page scrolls. It is not a drawer: the panel is content in the flow, it traps no focus and never locks the page.
Each header below runs in a page of its own, embedded here: the bar sticks, condenses and folds against that page, not against this article. Scroll inside a stage to watch the bar hold its place, change its width to 390 to see it fold, or open it alone from the bar above it.
A megamenu inside the panel
A megamenu can live inside iv-navbar__panel. From the lg breakpoint up its panels float under the whole bar; below it the navbar folds and the same panels behave as an accordion inside it. Pass data-iv-overlay="false" to the hosted menu: inside a header the bar is already the raised surface, and a scrim under it would dim the header itself.
Transparent over a cover
iv-navbar--transparent drops the background and borrows light text while the header sits over a hero; the moment it condenses or its panel opens, the surface and the page colours come back, because a transparent bar over content is unreadable. iv-navbar--glass keeps the blurred surface at every scroll position, and iv-navbar--center centres the links with the actions at the end.
Options
| Option | Attribute | Default | Effect |
|---|---|---|---|
collapseBelow | data-iv-collapse-below | lg | Breakpoint under which the panel folds behind the burger. none never folds. |
sticky | data-iv-sticky | false | Keep the header at the top of the viewport and condense it on scroll. |
condenseAt | data-iv-condense-at | 24 | Pixels of scroll before data-iv-condensed lands on the header. |
hideOnScroll | data-iv-hide-on-scroll | false | Slide the bar away while scrolling down, back on the way up. Never while the panel is open or focus is inside. |
closeOnOutside | data-iv-close-on-outside | true | A click outside the header closes the open panel. |
Methods and events
open(), close(reason), toggle(), destroy(); read isOpen and isCondensed. Above the collapse breakpoint open() is a no-op and isOpen stays false: there is nothing folded to unfold.
| Event | When | detail |
|---|---|---|
iv:open → iv:opened | the folded panel unfolds; the first is cancelable | reason, trigger |
iv:close → iv:closed | the panel folds again | reason: trigger, escape, external, api or viewport |
iv:condense | the header enters or leaves the condensed state | condensed |
Keyboard and assistive technology
The header is a <header> landmark and the links live in a <nav> with its own label. The burger is a real button with a name for screen readers, aria-expanded and aria-controls; Enter and Space work on it, Escape closes the panel and returns focus to the burger, and Tab walks the open panel in document order. The current page carries aria-current="page". No menu roles are used: these are links, not a menu. Crossing the breakpoint upwards closes the panel and hands the layout back to the bar.
Without JavaScript
Everything is reachable. Above collapseBelow the panel is a bar in line with the brand; below it the panel is served open and stacked, and the burger stays hidden because it would have nothing to toggle. Folding only happens under [data-iv-js], so a script that never loads cannot hide a menu. A sticky header is styled by CSS and needs no script either; only condensing, hiding on scroll and the folded panel do.
The panel is served open and init folds it, which moves the whole page down on a phone once the script runs. To fold from the first paint, mark the root before the stylesheet with one inline line in <head>: <script>document.documentElement.setAttribute("data-iv-js", "")</script>. Below lg the panel then starts folded and the toggle appears when init shows it; from lg up the bar is inline. Only the default breakpoint is known that early. If the script could fail to load, leave the marker out: a folded panel without its toggle is worse than a shift. The showcase recipe uses it.
Tokens and locals
| Local | Default | What it moves |
|---|---|---|
--iv-navbar-height | 4rem | Height of the bar at rest. |
--iv-navbar-height-condensed | 3.25rem | Height once the page has scrolled past condenseAt. |
--iv-navbar-bg | var(--iv-color-bg) | Surface of the bar. |
--iv-navbar-max | var(--iv-container-max) | Width the inner row is centred to. |
--iv-navbar-gap | var(--iv-space-5) | Gap between brand, navigation and actions. |
--iv-navbar-z | 150 | Stacking order against the page. |
State lives in attributes, so CSS can read it: data-iv-collapsible while the viewport is below the breakpoint, data-iv-open on the unfolded panel, data-iv-condensed after the scroll, data-iv-hidden on a bar slid away. The condensed bar takes --iv-shadow-ambient and a glass background; under reduced motion nothing travels, but data-iv-hidden still moves the bar out of the way because that is state, not decoration.
Common mistakes
- Serving the panel closed. Without the script nothing would open it; the markup must arrive usable and fold afterwards.
- Using the navbar as a drawer. If the navigation must cover the page and trap focus, that is drawer.
- Combining
hideOnScrollwith content that anchors to the top: the bar writesscroll-padding-block-startwhile sticky, but a jumping header still costs orientation. - A hosted megamenu with its overlay left on: the scrim dims the very bar you are reading from.