Skip to main content

Navigation

To create a site navigation use the nav element. It shows the full bar on wide screens and collapses the links behind a menu button below its breakpoint.

const elements = [
{
type: "nav", id: "nav",
brand: "Acme", // or an element spec: { type: "p", text, keySet, … }
items: [
{ title: "Work", link: "#work" },
{ title: "About", link: "#about" },
{ title: "Contact", link: "#contact" },
],
breakpoint: 768, // the full bar from here up (default "1200px")
font: "Inter", color: "#111",
hover: { color: "#b83a0b" },
background: "rgba(255, 255, 255, 0.8)",
radius: "14px",
mar: [{ a: 0 }], pad: [{ tb: 12, lr: 24 }],
keySet: [{ key: "backdropFilter", value: "blur(20px)" }],
menuLabel: "Menu",
},
];

Options​

optionwhat it does
itemsThe links, each { title, link } or a plain string. Declaring them is what builds the nav from these options.
brandThe name at the start of the bar — a string, or an element spec for full control of its type.
breakpointWidth from which the full bar shows; below it the links collapse behind the menu button. A number is px. Default "1200px".
font, colorThe links' font and colour (and a string brand's). color also colours the menu button unless hamburgerColour is given.
hoverLink hover styles, as on a.
background, radius, mar, padThe bar itself. Default margin [{a: 21}]; pass [{a: 0}] when a wrapper positions the bar.
keySetExtra CSS on the bar, desktop and mobile — e.g. backdropFilter, boxShadow, fontSize.
hamburgerColourColour of the menu button.
menuLabelAccessible name of the menu button. Default "Menu".

get_schema nav lists each of these with its shape, and validate_nodes checks them.

Behaviour​

  • The menu button is a real <button> with an accessible name and aria-expanded; it names the menu it controls.
  • Following a link closes the menu, so on a one-page site the menu does not cover the section it just scrolled to.
  • Prerendered pages carry the nav — as its phone view, at the prerenderer's emulated phone width — so crawlers and readers without JavaScript get the links.
  • To fix the bar to the top, wrap it: { type: "wrap", keySet: [{ key: "position", value: "fixed" }, …], children: [{ type: "nav", … }] }.

A nav declared without items renders the library's demo navigation (placeholder brand, links and a "More" dropdown), unchanged from earlier versions.

The imperative form​

The data form builds these classes; you can also use them directly. Switcher chooses a view by width; MobileBar and DesktopBar are the two views.

new Switcher().set({
id: "nav",
breakpoints: [
{ at: "0px", view: new MobileBar().set({
background: "#ecf0f1", radius: "1rem", hamburgerColour: "#111",
brand: new Text("Acme").set({ size: "S6" }),
}).add([
new Link().set({ url: "#work", text: "Work" }),
new Link().set({ url: "#about", text: "About" }),
]) },
{ at: "1200px", view: new DesktopBar().set({ background: "#ecf0f1", radius: "1rem" }).add([
new Text("Acme").set({ size: "S6" }), new Spacer(true),
new Link().set({ url: "#work", text: "Work" }),
new Link().set({ url: "#about", text: "About" }),
]) },
],
}).render("#mount");