DEV3 Technologies home

Collapsible admin sidebar

An admin sidebar that toggles between full width and an icon rail, keeping labels accessible and remembering nothing server side.

Tailwind CSSNavigationsidebaradmincollapselayout

Live preview

Code

<div class="flex min-h-screen bg-slate-50">
  <aside id="sidebar" data-collapsed="false"
    class="group flex w-60 shrink-0 flex-col border-r border-slate-200 bg-white p-3 transition-[width] duration-200 data-[collapsed=true]:w-16">
    <button id="sidebar-toggle" type="button" aria-expanded="true" aria-label="Collapse sidebar"
      class="mb-4 self-end rounded-lg p-2 text-slate-500 hover:bg-slate-100">
      <svg class="size-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M4 6h16M4 12h10M4 18h16"/></svg>
    </button>
    <nav aria-label="Admin">
      <ul class="space-y-1 text-sm font-medium text-slate-700">
        <li><a href="/admin" title="Overview" class="flex items-center gap-3 rounded-lg bg-indigo-50 px-3 py-2 text-indigo-700" aria-current="page">
          <svg class="size-5 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M3 12 12 4l9 8v8H3v-8Z"/></svg>
          <span class="group-data-[collapsed=true]:sr-only">Overview</span></a></li>
        <li><a href="/admin/orders" title="Orders" class="flex items-center gap-3 rounded-lg px-3 py-2 hover:bg-slate-100">
          <svg class="size-5 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M5 7h14l-1 12H6L5 7Zm4 0a3 3 0 0 1 6 0"/></svg>
          <span class="group-data-[collapsed=true]:sr-only">Orders</span></a></li>
        <li><a href="/admin/settings" title="Settings" class="flex items-center gap-3 rounded-lg px-3 py-2 hover:bg-slate-100">
          <svg class="size-5 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M12 3v3m0 12v3M3 12h3m12 0h3"/></svg>
          <span class="group-data-[collapsed=true]:sr-only">Settings</span></a></li>
      </ul>
    </nav>
  </aside>
  <main class="flex-1 p-6">Page content</main>
</div>

How it works

What it solves

Admin layouts need room for content, so a sidebar that shrinks to icons is a common request. The trick is doing it without duplicating markup or hiding link text from assistive tech when the rail is narrow.

How it works

The aside holds a data-collapsed attribute that Tailwind reads through the data-[collapsed=true]: variant. Width switches between w-60 and w-16 with a transition, and each label span uses group-data-[collapsed=true]:sr-only, so the text stays in the accessibility tree while disappearing visually. Links also carry a title so sighted rail users get a tooltip. The toggle button flips the attribute and updates aria-expanded and aria-label. On small screens the layout is a column, so the sidebar can simply stay full width.

Adapting it

Persist the choice by saving the attribute to localStorage inside a try block and restoring it on load. To overlay on mobile, change the aside to fixed below md and slide it with the drawer pattern. Add a badge by placing a span inside the link with an absolute position.

Pitfalls

  • Icon only links without title or hidden text are unlabeled.
  • Animating width reflows the content area; use will-change sparingly.
  • Active link styling must not depend on the label being visible.

How to use it

  1. Wrap your admin page in a flex container and paste sidebar.html as the first child.
  2. Load sidebar.js with defer.
  3. Replace the icon paths and link targets.
  4. Optionally store the collapsed state in your own preferences store and set the attribute server side.

Licence: DEV3 Snippet Licence. Free to use, change and ship in personal and commercial projects. Attribution is appreciated, not required. Please do not redistribute snippets as a collection.

Related snippets