Sidenav
A vertical menu for docs, admin and settings pages, with groups that collapse and a fold for small screens. No JavaScript.
Put .sidenav on a nav. Each
details is a group, and its summary is
the group label. Links go in a ul.
Current page
aria-current="page" on a link draws a bar on the guide
line and makes the text bold. A closed group that holds the current
page gets a stronger label, so readers still see where they are.
CSS cannot open a group, so add open to the group that
holds the current page when you render it. Give the groups the same
name to keep only one open at a time.
Nesting
A list or a details inside an li is one
level deeper, with its own guide line.
Groups that stay open
A heading followed by a ul is a group that does not
collapse. It looks the same as a details group, so you
can mix them.
Icons
A summary can start with an .icon or an inline SVG. It lines up with the label.
Small screens
Wrap the sidenav in a details with a summary. On wide
screens the summary hides and the menu shows. On screens under
48rem, or when the aside is wider than 24rem because it sits above
the content, the menu folds behind the summary. This site's own
menu works this way. The example below is folded because the
preview is wider than 24rem.
Menu
The fold measures the element around the details, so
that element needs a width from its layout. An aside
in .with-sidebar has one. Browsers without
::details-content keep the menu folded on every screen,
and it opens with a click.
Sticky
.sticky keeps the menu in view while the page scrolls,
below a .navbar.sticky when the page has one. A menu
taller than the screen scrolls on its own.
<div class="container with-sidebar">
<aside>
<details>
<summary>Menu</summary>
<nav class="sidenav sticky" aria-label="Documentation">...</nav>
</details>
</aside>
<main>...</main>
</div>
Variables
| Variable | Default |
|---|---|
--i-sidenav-font-size | 0.9375rem |
--i-sidenav-indentIndent of a nested list, where its guide line sits | 0.875rem |
--i-sidenav-link-padding-block | 0.25rem |
--i-sidenav-link-padding-inline | 1rem |
--i-sidenav-sticky-offsetGap above a sticky menu, added to the navbar height under a sticky navbar | var(--i-spacing) |
--i-sidenav-link-color-text | var(--i-color-subtle) |
--i-sidenav-link-hover-color-text | var(--i-color-text) |
--i-sidenav-label-color-text | var(--i-h3-color-text) |
--i-sidenav-color-border | var(--i-color-subtle-border) |
--i-sidenav-current-color-border | var(--i-color-primary) |
--i-sidenav-current-color-text | var(--i-h1-color-text) |