Collapsible Sidebar — Free HTML CSS JS Icon-Only Toggle Sidebar Snippet
Collapsible Sidebar · Layouts · Plain HTML, CSS & JS · Live preview
Copy & paste
Source Code
<div class="app-shell">
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<span class="logo-dot"></span>
<span class="logo-text">Acme</span>
<button class="collapse-btn" id="collapseBtn" onclick="toggleSidebar()" aria-label="Collapse sidebar" aria-expanded="true">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 18l-6-6 6-6"/></svg>
</button>
</div>
<nav class="nav-list">
<a href="#" class="nav-item active"><span class="nav-icon">D</span><span class="nav-label">Dashboard</span></a>
<a href="#" class="nav-item"><span class="nav-icon">P</span><span class="nav-label">Projects</span></a>
<a href="#" class="nav-item"><span class="nav-icon">T</span><span class="nav-label">Team</span></a>
<a href="#" class="nav-item"><span class="nav-icon">S</span><span class="nav-label">Settings</span></a>
</nav>
</aside>
<main class="main-content">
<h3>Main Content Area</h3>
<p>Toggle the sidebar using the arrow button in its header.</p>
</main>
</div>* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; background: #f8fafc; display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 24px; }
.app-shell { display: flex; height: 360px; border: 1px solid #e2e8f0; border-radius: 12px; overflow: hidden; }
.sidebar {
width: 220px;
background: #1e293b;
color: #e2e8f0;
transition: width 0.25s ease;
flex-shrink: 0;
overflow: hidden;
}
.sidebar.collapsed { width: 64px; }
.sidebar-header {
display: flex;
align-items: center;
gap: 10px;
padding: 16px;
border-bottom: 1px solid #334155;
white-space: nowrap;
}
.logo-dot { width: 22px; height: 22px; border-radius: 6px; background: #6366f1; flex-shrink: 0; }
.logo-text { font-weight: 700; font-size: 15px; flex: 1; opacity: 1; transition: opacity 0.15s; }
.sidebar.collapsed .logo-text { opacity: 0; width: 0; }
.collapse-btn {
width: 24px;
height: 24px;
border-radius: 6px;
border: none;
background: #334155;
color: #cbd5e1;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
flex-shrink: 0;
transition: transform 0.25s;
}
.sidebar.collapsed .collapse-btn { transform: rotate(180deg); }
.collapse-btn:hover { background: #475569; }
.nav-list { padding: 8px; display: flex; flex-direction: column; gap: 2px; }
.nav-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
border-radius: 8px;
color: #cbd5e1;
text-decoration: none;
font-size: 13px;
font-weight: 500;
white-space: nowrap;
transition: background 0.15s;
}
.nav-item:hover { background: #334155; }
.nav-item.active { background: #6366f1; color: #fff; }
.nav-icon {
width: 24px;
height: 24px;
border-radius: 6px;
background: #334155;
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 700;
flex-shrink: 0;
}
.nav-item.active .nav-icon { background: rgba(255,255,255,0.2); }
.nav-label { opacity: 1; transition: opacity 0.15s; }
.sidebar.collapsed .nav-label { opacity: 0; width: 0; overflow: hidden; }
.main-content { padding: 24px; flex: 1; }
.main-content h3 { font-size: 16px; color: #1e293b; margin-bottom: 8px; }
.main-content p { font-size: 13px; color: #64748b; }function toggleSidebar() {
const sidebar = document.getElementById('sidebar');
const btn = document.getElementById('collapseBtn');
const collapsed = sidebar.classList.toggle('collapsed');
btn.setAttribute('aria-expanded', String(!collapsed));
btn.setAttribute('aria-label', collapsed ? 'Expand sidebar' : 'Collapse sidebar');
}Extend with AI
Take This Snippet Further With AI
The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.
What's included
Features
About this UI Snippet
Collapsible Sidebar — HTML, CSS & JavaScript Icon Rail Toggle

Dashboards and admin panels almost always need a navigation sidebar, and power users almost always want the option to shrink it down once they've learned the icons and want more room for content. This snippet implements the classic "icon-only rail" collapse pattern used by tools like VS Code and Notion, built with a single boolean class toggle and a CSS width transition.
How the width animation works
The .sidebar has an explicit width: 220px and a transition: width 0.25s ease. Toggling the .collapsed class swaps that to width: 64px — just enough room for the icon column. Because both states are explicit pixel widths (not auto), the browser can smoothly animate between them; animating to/from width: auto is not reliably transitionable in CSS, which is a common trap when building this pattern from scratch.
How labels disappear without causing layout jumps
Simply hiding the .nav-label and .logo-text elements with display: none would make them disappear instantly, out of sync with the slower width animation, which looks broken. Instead, both fade via opacity (a separate, faster 0.15s transition) *and* collapse via width: 0; overflow: hidden, so the text visually fades away first and its space collapses in sync with the sidebar's own shrink, rather than the text abruptly vanishing or wrapping awkwardly mid-animation.
How the toggle button flips
The collapse button's chevron icon is rotated 180 degrees via transform: rotate(180deg) when .collapsed is active, which turns a "point left" icon into a "point right" icon using the same SVG — no separate icon asset needed for the two directions.
Accessibility handling
toggleSidebar() updates both aria-expanded and aria-label on the toggle button every time it's clicked, so assistive technology always announces the sidebar's current state and the action the button will perform next ("Expand sidebar" vs. "Collapse sidebar") rather than a static, potentially stale label.
Step by step
How to Use
- 1Load the snippetClick "Collapsible Sidebar" in the sidebar Library tab to load the app shell layout.
- 2Toggle the sidebarClick the arrow button in the sidebar header in the preview to collapse and expand it.
- 3Adjust the widthsChange the 220px and 64px values on .sidebar and .sidebar.collapsed in the CSS panel to fit your icon size.
- 4Add navigation itemsCopy a .nav-item anchor in the HTML panel and update its icon letter/label text.
- 5Persist the collapsed stateStore the collapsed boolean in localStorage inside toggleSidebar and read it back on page load to remember the user's preference.
- 6Export and saveExport as HTML/JSX/Tailwind or click "Save as" to reuse this shell across projects.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
CSS transitions cannot reliably animate to or from width: auto because the browser cannot interpolate an unknown target size. Using explicit values like 220px and 64px on both states lets the transition animate smoothly between two known numbers.
display: none changes instantly with no animation, which would make the text disappear abruptly out of sync with the slower sidebar width transition. Fading opacity first, then collapsing width, keeps the whole collapse feeling like one cohesive animation.
Inside toggleSidebar, save the new collapsed state to localStorage (e.g. localStorage.setItem('sidebarCollapsed', collapsed)). On page load, read that value and apply the .collapsed class immediately, before the user interacts with the toggle.
Copy an existing .nav-item anchor element inside .nav-list, update its icon letter (or swap in an SVG) and its .nav-label text, and update the href to point at the real route.
Yes — add a media query or a resize listener that adds the .collapsed class automatically below a chosen viewport width, while still letting the user manually toggle it back if there is room.
Rotating a single chevron SVG 180 degrees produces the mirrored "point the other way" icon without needing a second SVG asset or an icon font, keeping the markup smaller and the two states visually consistent.
Yes — the icon tiles remain fully sized and clickable in the collapsed state; only the text label collapses. Consider adding a title attribute or tooltip on each icon so users can identify items by hovering while collapsed.