webdevpuneet.com

Collapsible Sidebar Nav — Free HTML CSS Dashboard Snippet

Collapsible Sidebar Nav · Navigation · Plain HTML, CSS & JS · Live preview

CategoryNavigation

Copy & paste

Source Code

<div class="layout">
  <aside class="sidebar" id="sidebar" aria-label="Main navigation">
    <div class="sidebar-header">
      <div class="logo">
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 22 22 7 12 2"/></svg>
        <span class="logo-text">Nexus</span>
      </div>
      <button class="collapse-btn" id="collapseBtn" aria-label="Toggle sidebar" aria-expanded="true">
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="15 18 9 12 15 6"/></svg>
      </button>
    </div>

    <nav class="nav-section">
      <p class="nav-label">Main</p>
      <a class="nav-item active" href="#" data-tip="Dashboard">
        <svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
        <span class="nav-text">Dashboard</span>
        <span class="nav-badge">3</span>
      </a>
      <a class="nav-item" href="#" data-tip="Analytics">
        <svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>
        <span class="nav-text">Analytics</span>
      </a>
      <a class="nav-item" href="#" data-tip="Projects">
        <svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M3 7l9-4 9 4v13l-9 4-9-4z"/><polyline points="3 7 12 11 21 7"/><line x1="12" y1="11" x2="12" y2="22"/></svg>
        <span class="nav-text">Projects</span>
        <span class="nav-badge new">New</span>
      </a>
      <a class="nav-item" href="#" data-tip="Messages">
        <svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
        <span class="nav-text">Messages</span>
        <span class="nav-dot"></span>
      </a>
    </nav>

    <nav class="nav-section">
      <p class="nav-label">Management</p>
      <a class="nav-item" href="#" data-tip="Team">
        <svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
        <span class="nav-text">Team</span>
      </a>
      <a class="nav-item" href="#" data-tip="Files">
        <svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="13 2 13 9 20 9"/></svg>
        <span class="nav-text">Files</span>
      </a>
      <a class="nav-item" href="#" data-tip="Settings">
        <svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
        <span class="nav-text">Settings</span>
      </a>
    </nav>

    <div class="sidebar-footer">
      <div class="user-info" data-tip="Puneet Sharma">
        <div class="avatar">PS</div>
        <div class="user-details">
          <span class="user-name">Puneet Sharma</span>
          <span class="user-role">Admin</span>
        </div>
      </div>
    </div>
  </aside>

  <main class="main-content">
    <div class="topbar">
      <h1 class="page-title">Dashboard</h1>
      <div class="topbar-right">
        <span class="status-dot"></span>
        <span class="status-text">All systems normal</span>
      </div>
    </div>
    <div class="stats-row">
      <div class="stat-card"><span class="stat-num">2,847</span><span class="stat-label">Active Users</span></div>
      <div class="stat-card"><span class="stat-num">$18.2k</span><span class="stat-label">Revenue</span></div>
      <div class="stat-card"><span class="stat-num">94.3%</span><span class="stat-label">Uptime</span></div>
    </div>
    <p class="placeholder-text">Click the arrow to collapse the sidebar — icons stay visible with tooltips. Click again to expand.</p>
  </main>
</div>

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.

· Become a supporter

What's included

Features

Smooth width collapse animation
CSS width + min-width transition at cubic-bezier(.4,0,.2,1) collapses the sidebar from 220px to 60px without layout reflow or icon jumping.
CSS-only tooltip in collapsed state
::after pseudo-elements with content: attr(data-tip) render label tooltips without any JavaScript — one attribute per nav item is all that is needed.
Three badge styles
Numeric badge (purple), text badge ("New" — green), and notification dot (amber) demonstrate common sidebar notification patterns. All fade out when collapsed.
Arrow rotation indicator
The collapse button arrow rotates 180° via transform: rotate(180deg) on .collapsed .collapse-btn svg — a pure CSS direction indicator.
User profile footer
Initials-avatar with gradient background, username and role text. Fades gracefully in collapsed state, shows a tooltip on hover with the full name.
Section labels
.nav-label divides items into labelled sections ("Main", "Management"). Labels fade out in collapsed state to avoid cluttering the icon-only view.
Active state with accent colour
The .active class applies an indigo accent colour matching the logo and avatar gradient — visual coherence across the navigation chrome.
Single-line JS toggle
The entire collapse behaviour is one classList.toggle call — three lines of JS total. All animation, tooltip, and label logic lives in CSS.

About this UI Snippet

Collapsible Sidebar Nav — CSS Width Transition, Icon Tooltip System & Active State Design

Screenshot of the Collapsible Sidebar Nav snippet rendered live

The collapsible sidebar is the defining pattern of dashboard UI design — a persistent navigation panel that maximises screen space when collapsed to icon-only view while remaining fully navigable. This snippet builds a production-quality sidebar in pure HTML and CSS, with a single JavaScript toggle: smooth width animation, labelled nav items with icon fallback, badge counters, notification dots, a user profile footer, and CSS-only tooltips in the collapsed state.

Dashboards are where developers most often need a sidebar, and getting it right requires solving several simultaneous problems: the panel must animate smoothly without layout reflow, labels must hide without leaving gaps, icons must remain accessible in collapsed state (with tooltips), and badges must not clutter the icon view.

The width collapse animation

The sidebar collapses by toggling a .collapsed class that changes width and min-width from 220px to 60px. Both properties are animated with transition: width .28s cubic-bezier(.4,0,.2,1) — the Material Design standard easing for panel motions. Using min-width alongside width prevents the flex container from shrinking below the target during animation. The content inside (logo-text, nav-text, badges, labels) fades out with opacity: 0 and width: 0, which collapses their space without affecting the icon alignment.

CSS-only tooltips in collapsed state

Each .nav-item carries a data-tip attribute with its label text. The collapsed state uses an ::after pseudo-element with content: attr(data-tip) to render this as a floating tooltip. The tooltip is positioned left: calc(100% + 10px) — to the right of the icon — with a dark background and border to match the sidebar theme. pointer-events: none prevents it interfering with clicks. Visibility is controlled with opacity: 0 + opacity: 1 on hover — no JavaScript needed for the tooltip system.

Badge and notification dot system

Three badge styles are demonstrated: a purple numeric badge (3), a green "New" label badge, and a yellow notification dot. In collapsed state, all badges have opacity: 0 — they would crowd the icon-only view. The icons alone communicate location; users expand the sidebar to check counts. This pattern matches VS Code, Linear, and Notion's sidebar behaviour.

Active state with accent colour

The active nav item uses background: #334155 and color: #818cf8 (indigo accent). This accent colour matches the logo icon and the user avatar gradient, creating visual coherence across the sidebar. The active state is set in HTML via the .active class — in a real app, your router would apply this dynamically.

User profile footer

The sidebar footer contains an avatar (initials-based <div> with gradient background), username, and role label. In collapsed state, the details fade out and the avatar tooltip shows the full name. This footer is a standard dashboard pattern — it anchors the user's identity in the navigation chrome and provides a consistent entry point for profile/account settings. Pair with a command palette for keyboard navigation between sections.

Step by step

How to Use

  1. 1
    Paste the three code blocksDrop the HTML, CSS, and JS into your page. A full-height layout appears with a 220px sidebar on the left and a main content area on the right.
  2. 2
    Click the collapse arrowThe sidebar smoothly animates to 60px — labels, badges, and the logo text fade out. Only icons remain, bottom-aligned.
  3. 3
    Hover over icons in collapsed stateA CSS tooltip appears to the right of each icon showing its label. The user avatar tooltip shows the full name. No JavaScript required.
  4. 4
    Click again to expandThe collapse arrow rotates 180° and the sidebar expands back to 220px. Labels, badges, and the user details fade back in.
  5. 5
    Set an active itemAdd the .active class to any .nav-item to highlight it with the accent colour. In a real app, apply this based on the current route.
  6. 6
    Add your nav itemsCopy any .nav-item block, swap the SVG icon, update the data-tip attribute, label text, and optionally add a badge or dot. Sections are grouped by .nav-section.

Real-world uses

Common Use Cases

SaaS dashboard navigation
The primary use case — a persistent left panel for navigating between dashboard sections. Collapse to give more space to data tables and charts.
Admin panels and CMS interfaces
Content management systems, e-commerce admin panels, and CRMs all use collapsible sidebars to balance navigation access with content editing space.
Productivity app layouts
Project management tools (Notion, Linear, Asana pattern) use a collapsible sidebar with icons + labels. The badge system communicates unread counts and new items.
Developer tooling interfaces
Code editors, database GUIs, and API testing tools use icon-only sidebars at small screen sizes. The tooltip system provides label access without expanding.
Documentation sites
Technical documentation with many sections benefits from a collapsible tree-style sidebar. Pair with a table of contents for per-page navigation.
Analytics and reporting dashboards
Financial dashboards, analytics platforms, and reporting tools use the sidebar for section navigation while the main area renders data-dense charts and tables.

Got questions?

Frequently Asked Questions

Save the state to localStorage on toggle: localStorage.setItem('sidebar_collapsed', isCollapsed). On page load, read it: if (localStorage.getItem('sidebar_collapsed') === 'true') sidebar.classList.add('collapsed').

On mobile breakpoints (max-width: 768px), position the sidebar with position: fixed; left: -220px by default, and left: 0 when open. Add an overlay backdrop behind it. The toggle button would move to the topbar. See the drawer snippet for the full pattern.

Add a <div class="sub-menu"> inside a nav item. Toggle a .open class on click. Use max-height: 0 → max-height: 200px with a CSS transition for a smooth expand. The parent item needs a chevron icon that rotates on .open.

Replace the toggle JS with const [collapsed, setCollapsed] = useState(false). Apply className={sidebar${collapsed ? ' collapsed' : ''}} to the aside. The collapse button's onClick calls setCollapsed(c => !c). Active state comes from comparing the current route to each item's href using Next.js usePathname() or React Router useLocation().

Yes. While the Collapsible Sidebar Nav snippet gives you one pattern to copy, the free Responsive Navbar Builder at webdevpuneet.com/navbar-builder/ designs a whole navigation bar: logo, links and dropdown menus, a mobile hamburger menu (dropdown panel, slide-in drawer or full screen) and a scroll effect (sticky, shrink, hide on scroll or transparent). It has six presets, a live preview that runs the real code, and exports HTML + CSS + vanilla JS, React, Tailwind, Vue 3 or Angular — or you can click Fork & Edit to keep editing it in My Code.