use UI

Sidebar & Rail

Also called side nav, nav rail, app navigation, left nav

A persistent vertical navigation region beside the main content, optionally collapsed to icons.

Example

Analytics

The sidebar stays put while this changes. That permanence is the whole point — the current place is answered without opening anything.

Accessible names in expanded mode

Overview · Analytics · Documents · Team · Settings

Identical in both modes. Collapsing changes what is painted, not what is announced — and the current destination carries aria-current="page" rather than only a background colour.

When to use it

  • The app has a stable set of top-level places people move between all day.
  • The current location needs to stay visible while working — a dashboard, an editor, an admin panel.
  • There is horizontal room to spare, or the layout can afford a rail when there is not.

When not to

  • There are three destinations. A horizontal nav in the header costs nothing and reads faster.
  • The content needs the full width — a document editor, a canvas, a data table with twenty columns.
  • The destinations are marketing pages with deep sub-structure. That is a header nav, possibly a mega menu.

Trade-offs

  • Always visible, so the current place and the available places are answered without interaction.
  • Scales down to a rail instead of disappearing entirely, unlike a header nav.
  • Vertical lists take more items comfortably than a horizontal row does.
  • Costs 200–280px of width permanently, which is a lot on a laptop.
  • The rail hides labels, and icon-only navigation is guessy for anything beyond the obvious five.
  • Grows badly: teams keep adding items until it needs sections, and then it needs a scrollbar.

Accessibility

What this pattern needs in order to work for everyone.

Keyboard
  • Plain links in a list. Tab moves through them; do not intercept the arrow keys unless you have built a full menubar, which a sidebar is not.
  • Collapsing must not change the tab order or drop items — the rail has exactly the same destinations as the expanded state.
  • Give it a skip link if it is long. Tabbing past fifteen nav items to reach the content is a daily tax.
Roles and state
  • Wrap it in `<nav>` with a label. If there are two navs on the page, both need distinct labels — “Main” and “Account”, not two anonymous regions.
  • Mark the current destination with `aria-current="page"`. Highlighting it with background colour alone says nothing to a screen reader.
  • In rail mode the label is still required: keep the text and hide it visually with a screen-reader-only class, or the link's accessible name becomes the icon's file name — or nothing at all.
  • The collapse toggle is a button with `aria-expanded` and a name that says what it does — “Collapse sidebar”, not a bare chevron.
Focus
Collapsing or expanding keeps focus on the toggle. On mobile, where the sidebar becomes a drawer, it is a dialog: focus goes in, is trapped, Escape closes, and focus returns to the opener.

In the wild

  • Linear Persistent sidebar with sections, collapsing to a rail that keeps every destination reachable.
  • VS Code activity bar A rail by default, with labels in tooltips and the full names kept in the accessibility tree.

Compared with

Side-by-side breakdowns of patterns that solve a similar problem.