Utilities✨ Premium

Sidebar Toggle

Icon sidebar with a chevron button: expanded, it goes from 80 to 160 px, names its links, and the content beside it rearranges itself.

CSS@containerSidebar

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

Halvorde — collapsed menu of warehouse software — Sidebar Toggle example 1

① Halvorde — collapsed menu of warehouse software

WhenFull-frame inventory screen: icon bar on the left, two counters and the item table on the right. The chevron expands the menu (Home, Stock, Settings); the content narrows and the table's “Location” column hides for lack of room.
WhyPickers keep the table wide most of the time and only open the menu names when needed, without leaving the screen.
SettingsRoot at height: 100%, transparent background; .csb-main holds the title, two .csb-block tiles and a table. The hidden column comes from a scene rule on the csb-main container (max-width: 330px). For the capture, the chevron is clicked every 1.3 s.
Virdanne — “Layers” palette of a floor-plan editor — Sidebar Toggle example 2

② Virdanne — “Layers” palette of a floor-plan editor

WhenHouse floor-plan editor: a floating palette at the top left shows only three layer icons (walls, furniture, dimensions). The chevron widens it to 160 px and names each layer; the plan stays visible behind it.
WhyA tool palette should get in the way of drawing as little as possible: collapsed by default, it opens just long enough to pick a layer.
SettingsRoot at width: auto in a width: max-content window; .csb-main hidden (the palette has no content beside it). Ruler icon added for dimensions. Chevron clicked every 1.3 s for the capture.
Corduval — chapters of a guitar course on a phone — Sidebar Toggle example 3

③ Corduval — chapters of a guitar course on a phone

WhenPhone in landscape during a video lesson: a rail of three chapter icons left of the video. The chevron reveals the titles (Introduction, Chords, Strumming); the video shrinks without being cropped.
WhyOn a small screen the video keeps as much room as possible; titles only show when you want to switch chapters.
SettingsRoot at height: 100% in a 402 × 210 px screen, #16100c background, orange accent through the button and active-link colours. .csb-main holds the video and the lesson title. Chevron clicked every 1.3 s for the capture.

How it works

The .fx-0752-root element holds a .csb-scene row: on the left the <nav class="csb-panel"> (the .csb-toggle button, then one .csb-item link per entry), on the right the .csb-main area. The button adds or removes the is-expanded class on the bar and updates its aria-expanded; the width goes from 80 to 160 px in 0.4 s and the chevron turns half a turn.

The bar is itself a container (container: csb-panel / inline-size). Collapsed, its usable width is 67 px: the .csb-text labels are hidden from sight but still read, and the icons are centred. From 100 usable px (so once expanded), @container csb-panel (min-width: 100px) shows the labels and left-aligns the links. The bar's width decides, not the button state: if you force a 120 px width in CSS, the labels show too.

The main area is a second container (csb-main): its .csb-block tiles (a .csb-num figure and its .csb-cap caption) sit in one column below 180 px and in two from 180 px. When the bar expands, the content loses 80 px and rearranges itself. The script attaches to each root, once, with no id: two copies on one page open independently.

Accessibility

  • Announced button: a real <button type="button"> named “Show menu labels”, with aria-expanded set to false or true; Enter and Space activate it.
  • Links named even when collapsed: labels are hidden from sight (1 px box), not removed; a screen reader reads “Projects, link” in the 80 px bar. Icons carry aria-hidden="true".
  • Current page: aria-current="page" on the active link, moved on click by the script.
  • Visible focus: 2 px #a78bfa outline on the button and the links. In Safari, Tab only stops on links with Option+Tab or the macOS keyboard setting.
  • Reduced motion: under prefers-reduced-motion: reduce, the bar changes width at once and the chevron flips without rotating; opening works exactly the same.

Browser compatibility

Container queries (Chrome 105, Firefox 110, Safari 16) and :focus-visible (Safari 15.4). Measured in Chromium 151, Firefox 153 and WebKit 26.5 with two copies on one page: the 2nd copy's button opens only the 2nd (80 → 160 px, aria-expanded="true", 36 to 49 px labels visible), keyboard and touch included; tiles in 2 columns from 180 px of content; 0 errors.

Chrome 105+✓ Full (measured)
Firefox 110+✓ Full (measured)
Safari 16+✓ Full (measured in WebKit)
Edge 105+✓ Full
Mobile iOS 16+✓ Full
Android Chrome 105+✓ Full

Without container queries, the button still widens the bar but labels stay hidden from sight (screen readers still read them) and the tiles stay in one column. Without JavaScript, the bar stays collapsed.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0752-root">
  <div class="csb-scene">
    <nav class="csb-panel" aria-label="…">
      <button type="button" class="csb-toggle" aria-expanded="false" aria-label="…">…</button>
      <a class="csb-item" href="#…" aria-current="page">
        <svg aria-hidden="true">…</svg>
        <span class="csb-text">…</span>
      </a>
    </nav>
    <div class="csb-main">
      <p class="csb-title">…</p>
      <div class="csb-blocks">
        <div class="csb-block"><span class="csb-num">…</span><span class="csb-cap">…</span></div>
      </div>
    </div>
  </div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Widths (CSS — .csb-panel and .csb-panel.is-expanded) 80 px collapsed, 160 px expanded Keep the collapsed width below the label breakpoint and the expanded width above it.
Label breakpoint (CSS — @container csb-panel (min-width: 100px)) 100 px of usable width Raise it if you widen the collapsed bar (otherwise labels would show from the start).
Content breakpoint (CSS — @container csb-main (min-width: 180px)) Tiles in 1 column, then 2 from 180 px Add more breakpoints on csb-main for your own content (table, cards).
State on load (HTML — is-expanded class on .csb-panel) Collapsed Add the class to start expanded; the script aligns aria-expanded on load.
Entries (HTML — .csb-item) Home, Projects, Settings One link per entry with its SVG icon and its .csb-text; aria-current="page" on the current page.
Colours (CSS) Button rgba(139,92,246,.2) and chevron #8b5cf6, active link rgba(139,92,246,.2) Replace them on .csb-toggle, .csb-toggle svg and .csb-item[aria-current].
Duration (CSS — transition: width .4s on .csb-panel) 0.4 s; chevron 0.3 s Shorten or remove the transition; reduced motion already removes it.

FAQ

Because of the width. The button only widens the bar; the @container rule shows the labels once the bar exceeds 100 usable px. A bar widened any other way (CSS, another script) shows them too.
Yes. Each root gets its own wiring, with no id: one bar's chevron only opens that bar, even if the script is pasted twice.
The effect does not do it. Store the state in your own code (cookie, localStorage) and put the is-expanded class on .csb-panel on load: the script then syncs aria-expanded.