Sidebar Collapse
Sidebar that follows the available room: icons only below a 350 px container, a 140 px column with labels above, 200 px from 500 px.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Utilities has 43 effects, including 3 free. Explore the category →
3 usage examples



How it works
The .fx-0762-root element is the queried container (container: wsb-side / inline-size). It holds a two-column .wsb-layout grid: the <nav class="wsb-panel"> bar (one .wsb-item link per entry, SVG icon and <span class="wsb-label">) and the .wsb-main area where your content goes. There is no button and no state: only the root's width decides.
Below 350 px the grid is 40px 1fr: the bar shows icons only, labels are hidden from sight but still read. From 350 px the column grows to 140 px and the labels show; from 500 px it grows to 200 px and the links get larger (0.8 rem, 8 × 10 px padding). Switching columns animates over 0.4 s (grid-template-columns). A label too long for its column ends with an ellipsis instead of overflowing.
The small script moves aria-current="page" to the clicked link, once per root even if the code is pasted twice. It is optional: on a multi-page site, set the attribute on the server.
Accessibility
- Links named at every width: in icon mode labels are hidden from sight (1 px box), not removed: “Search, link” is read even in the 40 px column. Icons carry
aria-hidden="true". - Real links:
<a href>inside a<nav aria-label>, current page marked witharia-current="page". In Safari, Tab only stops on links with Option+Tab or the macOS keyboard setting. - Visible focus: 2 px
#a78bfaoutline drawn inside the link (−2 px offset) so it stays visible in the narrow column. - In icon mode, no tooltip is provided: if your icons are not self-explanatory, add a
titleto each link or keep the root above 350 px. - Reduced motion: under
prefers-reduced-motion: reduce, the column changes width at once and hover fades are removed.
Browser compatibility
Container queries (Chrome 105, Firefox 110, Safari 16); animating grid-template-columns needs Chrome 107 or Safari 16 (before that, the change is instant). Measured in Chromium 151, Firefox 153 and WebKit 26.5: 40 px column up to 349 px, 140 px from 351 to 499 px with whole labels (“Settings” fits), 200 px from 501 px; two copies independent on click, tap and Enter; 0 errors.
Without container queries, the bar stays icon-only (40 px column) at every width; links stay named for screen readers and work.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0762-root">
<div class="wsb-layout">
<nav class="wsb-panel" aria-label="…">
<a class="wsb-item" href="#…" aria-current="page">
<svg aria-hidden="true">…</svg>
<span class="wsb-label">…</span>
</a>
<a class="wsb-item" href="#…">…</a>
</nav>
<div class="wsb-main">…</div>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Breakpoints (CSS — @container wsb-side (min-width: 350px) and (min-width: 500px)) |
350 px labels, 500 px wide column | Put the first one where your longest label fits in the column. |
Column widths (CSS — grid-template-columns on .wsb-layout) |
40 px, then 140 px, then 200 px | Change the three values; the narrow column must stay ≥ 40 px for 16 px icons. |
Entries (HTML — .wsb-item) |
Home, Search, Profile, Settings | One link per entry with its icon and its .wsb-label; aria-current="page" on the current page. |
Content (HTML — .wsb-main) |
“Main content”, centred | Put your page in it; switch it to display: block for column content. |
Minimum height (CSS — min-height on .wsb-layout) |
140 px | Give the root and the grid height: 100% to fill a window or a panel. |
| Colours (CSS) | Bar rgba(255,255,255,.05), links rgba(255,255,255,.6), active rgba(139,92,246,.2) |
Replace them on .wsb-panel, .wsb-item and .wsb-item[aria-current]. |
Transition (CSS — transition on .wsb-layout) |
0.4 s, cubic-bezier(.4,0,.2,1) |
Remove it for an instant switch; reduced motion already removes it. |
FAQ
width: 220px): the bar follows by itself, with no other setting.