30 CSS Sidebar Layouts
05 / 30

All 30 in 30 CSS Sidebar Layouts

  1. 01Modern SaaS Dashboard Sidebar Menu with Native Dark Mode Switch
  2. 02Accessible Admin Panel Sidebar with CSS Tooltips and Icon Collapse
  3. 03Developer Documentation Sidebar with Scroll-Synced Nesting
  4. 04Mobile-First Responsive Sidebar to Bottom Navigation Switch Layout
  5. 05Data Analytics Sidebar Layout with CSS Subgrid Alignment
  6. 06Smooth Animated Collapsible Sidebar Menu with Icon-Only Mode
  7. 07CSS Position Sticky Sidebar Layout for E-Commerce and Blogs
  8. 08Pure CSS Collapsible Sidebar Drawer Menu without JavaScript
  9. 09CSS Fixed Sidebar Layout with Independent Scrollable Main Content
  10. 10Off-Canvas Navigation Drawer for Mobile & Desktop Web Apps
  11. 11Right-Aligned CSS Sidebar Layout for Secondary Tool Panels
  12. 12Two-Pane Webmail UI Layout with CSS Flexbox & Grid
  13. 13Dual Sidebar App Shell Layout with Left Nav and Right Context Panel
  14. 14Compact Mini Icon Rail Sidebar Navigation for SaaS Web Apps
  15. 15Responsive E-Commerce Product Filter Sidebar with Native Accordion Menu
  16. 16Modern Floating Glassmorphism Sidebar UI Component
  17. 17CSS Sidebar Menu with Sticky User Profile Footer
  18. 18Push Content Sidebar Navigation Layout with Smooth CSS Transitions
  19. 19Off-Canvas Sidebar Overlay Layout with Blur Backdrop
  20. 20Persistent Collapsible State Sidebar with CSS Variables
  21. 21App Sidebar Navigation with Integrated Sticky Search Bar
  22. 22Section-Grouped Sidebar Navigation Menu with Header Labels
  23. 23CSS Target Active Indicator Sidebar Menu without JavaScript
  24. 24Multi-Level Nested Tree Sidebar Navigation Layout
  25. 25Multi-Tab Sidebar UI Component with Dynamic Panel Switching
  26. 26Onboarding Wizard Sidebar Layout with Step Progress Tracking
  27. 27Pure CSS Resizable Sidebar Layout Using Resize Property
  28. 28Three-Pane Productivity Workspace Shell Layout
  29. 29Next-Gen Adaptive Sidebar Layout Using CSS Container Queries
  30. 30Frosted Glass Floating Sidebar Layout with Backdrop Blur
Pure CSSMIT licensed

Data Analytics Sidebar Layout with CSS Subgrid Alignment

The alignment problem every dashboard sidebar has — icons, labels of wildly different lengths, live metric values, and status badges drifting out of column — solved properly with grid-template-columns: subgrid. Every row inherits the SAME four tracks from the list parent, so '99.98%' under 'Uptime' and '4' under 'Alerts' sit on identical rails, no hard-coded widths anywhere.

Live Demo
Plain CSSTailwind v4
Try it

Mosaic by Cruip: a complete Tailwind admin dashboard template in HTML, React, Next.js and Vue · $69

Cruip · Mosaic by Cruip · Affiliate link

View Mosaic dashboard

The code

<section class="sbl-06">
  <aside class="sbl-06__rail" aria-label="Service metrics">
    <h2 class="sbl-06__brand">ops<span>/grid</span></h2>
    <ul class="sbl-06__list">
      <li class="sbl-06__head">Core services</li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="5" width="18" height="6" rx="1.5"/><rect x="3" y="13" width="18" height="6" rx="1.5"/><path d="M6.5 8h.01M6.5 16h.01"/></svg><a href="#">API gateway</a><data value="99.98">99.98%</data><span class="sbl-06__dot sbl-06__dot--ok" title="Healthy"></span></li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><ellipse cx="12" cy="6" rx="8" ry="3"/><path d="M4 6v12c0 1.7 3.6 3 8 3s8-1.3 8-3V6M4 12c0 1.7 3.6 3 8 3s8-1.3 8-3"/></svg><a href="#">Postgres primary</a><data value="12">12ms</data><span class="sbl-06__dot sbl-06__dot--ok" title="Healthy"></span></li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M13 3 4 14h6l-1 7 9-11h-6z"/></svg><a href="#">Job queue</a><data value="1482">1,482</data><span class="sbl-06__dot sbl-06__dot--warn" title="Degraded"></span></li>
      <li class="sbl-06__head">Observability</li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 20V10m6 10V4m6 16v-7"/></svg><a href="#">Error rate</a><data value="0.42">0.42%</data><span class="sbl-06__dot sbl-06__dot--ok" title="Healthy"></span></li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18 8a6 6 0 1 0-12 0c0 7-3 8-3 8h18s-3-1-3-8m-4.3 11a2 2 0 0 1-3.4 0"/></svg><a href="#">Open alerts</a><data value="4">4</data><span class="sbl-06__dot sbl-06__dot--crit" title="Critical"></span></li>
    </ul>
  </aside>
  <main class="sbl-06__main"><h1>Infrastructure</h1><p>Labels, values and badges align on shared subgrid rails — inspect the value column: no fixed widths anywhere.</p></main>
</section>
.sbl-06,
.sbl-06 *,
.sbl-06 *::before,
.sbl-06 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sbl-06 {
  --panel: oklch(0.16 0.015 260);
  --ink: oklch(0.93 0.005 260);
  --mut: oklch(0.62 0.012 260);
  --line: oklch(0.27 0.015 260);
  --ok: oklch(0.75 0.17 155);
  --warn: oklch(0.8 0.15 85);
  --crit: oklch(0.66 0.21 25);
  display: grid;
  grid-template-columns: 288px 1fr;
  height: 100vh;
  height: 100dvh;
  font-family: system-ui,'Segoe UI',sans-serif;
  background: oklch(0.13 0.012 260);
  color: var(--ink);
}

.sbl-06__rail {
  background: var(--panel);
  border-right: 1px solid var(--line);
  padding: 20px 14px;
  overflow-y: auto;
}

.sbl-06__brand {
  font: 700 15px/1 ui-monospace,Menlo,monospace;
  padding: 2px 8px 18px;
}

.sbl-06__brand span {
  color: var(--mut);
}

.sbl-06__list {
  list-style: none;
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: 2px 0;
}

.sbl-06__head {
  grid-column: 1/-1;
  font: 600 10.5px/1 system-ui,sans-serif;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--mut);
  padding: 16px 8px 8px;
}

.sbl-06__row {
  grid-column: 1/-1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: center;
  column-gap: 11px;
  min-height: 40px;
  padding: 0 8px;
  border-radius: 9px;
  transition: background-color .15s ease;
}

.sbl-06__row:hover {
  background: color-mix(in oklab,var(--ink) 6%,transparent);
}

.sbl-06__row svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: var(--mut);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sbl-06__row a {
  font: 500 13.5px/1 system-ui,sans-serif;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sbl-06__row a:focus-visible {
  outline: 2px solid var(--ok);
  outline-offset: 3px;
  border-radius: 4px;
}

.sbl-06__row data {
  font: 500 12.5px/1 ui-monospace,Menlo,monospace;
  font-variant-numeric: tabular-nums;
  color: var(--mut);
  text-align: end;
}

.sbl-06__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  justify-self: center;
}

.sbl-06__dot--ok {
  background: var(--ok);
  box-shadow: 0 0 8px color-mix(in oklab,var(--ok) 60%,transparent);
}

.sbl-06__dot--warn {
  background: var(--warn);
  box-shadow: 0 0 8px color-mix(in oklab,var(--warn) 60%,transparent);
}

.sbl-06__dot--crit {
  background: var(--crit);
  box-shadow: 0 0 8px color-mix(in oklab,var(--crit) 60%,transparent);
}

.sbl-06__main {
  padding: 32px;
  overflow-y: auto;
}

.sbl-06__main h1 {
  font: 600 22px/1.2 system-ui,sans-serif;
  margin-bottom: 10px;
}

.sbl-06__main p {
  color: var(--mut);
  font-size: 14px;
  line-height: 1.6;
  max-width: 48ch;
  text-wrap: pretty;
}

@media (prefers-reduced-motion: reduce) {
  .sbl-06__row {
    transition: none;
  }
}
/* No JavaScript — the <ul> owns four master tracks; every <li> is grid-template-columns:subgrid, so values and badges align across rows with no fixed widths. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Sidebar Layout from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Data Analytics Sidebar Layout with CSS Subgrid Alignment
Source: https://codefronts.com/layouts/css-sidebar-layouts/data-analytics-sidebar-layout-with-css-subgrid-alignment/

The alignment problem every dashboard sidebar has — icons, labels of wildly different lengths, live metric values, and status badges drifting out of column — solved properly with grid-template-columns: subgrid. Every row inherits the SAME four tracks from the list parent, so '99.98%' under 'Uptime' and '4' under 'Alerts' sit on identical rails, no hard-coded widths anywhere.
## HTML
```html
<section class="sbl-06">
  <aside class="sbl-06__rail" aria-label="Service metrics">
    <h2 class="sbl-06__brand">ops<span>/grid</span></h2>
    <ul class="sbl-06__list">
      <li class="sbl-06__head">Core services</li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="5" width="18" height="6" rx="1.5"/><rect x="3" y="13" width="18" height="6" rx="1.5"/><path d="M6.5 8h.01M6.5 16h.01"/></svg><a href="#">API gateway</a><data value="99.98">99.98%</data><span class="sbl-06__dot sbl-06__dot--ok" title="Healthy"></span></li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><ellipse cx="12" cy="6" rx="8" ry="3"/><path d="M4 6v12c0 1.7 3.6 3 8 3s8-1.3 8-3V6M4 12c0 1.7 3.6 3 8 3s8-1.3 8-3"/></svg><a href="#">Postgres primary</a><data value="12">12ms</data><span class="sbl-06__dot sbl-06__dot--ok" title="Healthy"></span></li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M13 3 4 14h6l-1 7 9-11h-6z"/></svg><a href="#">Job queue</a><data value="1482">1,482</data><span class="sbl-06__dot sbl-06__dot--warn" title="Degraded"></span></li>
      <li class="sbl-06__head">Observability</li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 20V10m6 10V4m6 16v-7"/></svg><a href="#">Error rate</a><data value="0.42">0.42%</data><span class="sbl-06__dot sbl-06__dot--ok" title="Healthy"></span></li>
      <li class="sbl-06__row"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18 8a6 6 0 1 0-12 0c0 7-3 8-3 8h18s-3-1-3-8m-4.3 11a2 2 0 0 1-3.4 0"/></svg><a href="#">Open alerts</a><data value="4">4</data><span class="sbl-06__dot sbl-06__dot--crit" title="Critical"></span></li>
    </ul>
  </aside>
  <main class="sbl-06__main"><h1>Infrastructure</h1><p>Labels, values and badges align on shared subgrid rails — inspect the value column: no fixed widths anywhere.</p></main>
</section>
```
## CSS
```css
.sbl-06,
.sbl-06 *,
.sbl-06 *::before,
.sbl-06 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sbl-06 {
  --panel: oklch(0.16 0.015 260);
  --ink: oklch(0.93 0.005 260);
  --mut: oklch(0.62 0.012 260);
  --line: oklch(0.27 0.015 260);
  --ok: oklch(0.75 0.17 155);
  --warn: oklch(0.8 0.15 85);
  --crit: oklch(0.66 0.21 25);
  display: grid;
  grid-template-columns: 288px 1fr;
  height: 100vh;
  height: 100dvh;
  font-family: system-ui,'Segoe UI',sans-serif;
  background: oklch(0.13 0.012 260);
  color: var(--ink);
}

.sbl-06__rail {
  background: var(--panel);
  border-right: 1px solid var(--line);
  padding: 20px 14px;
  overflow-y: auto;
}

.sbl-06__brand {
  font: 700 15px/1 ui-monospace,Menlo,monospace;
  padding: 2px 8px 18px;
}

.sbl-06__brand span {
  color: var(--mut);
}

.sbl-06__list {
  list-style: none;
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: 2px 0;
}

.sbl-06__head {
  grid-column: 1/-1;
  font: 600 10.5px/1 system-ui,sans-serif;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--mut);
  padding: 16px 8px 8px;
}

.sbl-06__row {
  grid-column: 1/-1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: center;
  column-gap: 11px;
  min-height: 40px;
  padding: 0 8px;
  border-radius: 9px;
  transition: background-color .15s ease;
}

.sbl-06__row:hover {
  background: color-mix(in oklab,var(--ink) 6%,transparent);
}

.sbl-06__row svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: var(--mut);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sbl-06__row a {
  font: 500 13.5px/1 system-ui,sans-serif;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sbl-06__row a:focus-visible {
  outline: 2px solid var(--ok);
  outline-offset: 3px;
  border-radius: 4px;
}

.sbl-06__row data {
  font: 500 12.5px/1 ui-monospace,Menlo,monospace;
  font-variant-numeric: tabular-nums;
  color: var(--mut);
  text-align: end;
}

.sbl-06__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  justify-self: center;
}

.sbl-06__dot--ok {
  background: var(--ok);
  box-shadow: 0 0 8px color-mix(in oklab,var(--ok) 60%,transparent);
}

.sbl-06__dot--warn {
  background: var(--warn);
  box-shadow: 0 0 8px color-mix(in oklab,var(--warn) 60%,transparent);
}

.sbl-06__dot--crit {
  background: var(--crit);
  box-shadow: 0 0 8px color-mix(in oklab,var(--crit) 60%,transparent);
}

.sbl-06__main {
  padding: 32px;
  overflow-y: auto;
}

.sbl-06__main h1 {
  font: 600 22px/1.2 system-ui,sans-serif;
  margin-bottom: 10px;
}

.sbl-06__main p {
  color: var(--mut);
  font-size: 14px;
  line-height: 1.6;
  max-width: 48ch;
  text-wrap: pretty;
}

@media (prefers-reduced-motion: reduce) {
  .sbl-06__row {
    transition: none;
  }
}
```

## JavaScript
```js
/* No JavaScript — the <ul> owns four master tracks; every <li> is grid-template-columns:subgrid, so values and badges align across rows with no fixed widths. */
```

How this works

The parent <ul> declares the master tracks once: grid-template-columns:auto 1fr auto auto — icon, label, value, badge. Each <li> then spans all four (grid-column:1/-1) and declares display:grid; grid-template-columns:subgrid — meaning 'lay my children on my parent's rails'. The result is the table-like alignment designers actually want from a metrics rail: the value column is exactly as wide as its widest member, across every row, and grows automatically when a number gains a digit. Before subgrid this took a real <table> or fragile fixed widths.

The demo doubles down by grouping rows under section headers — the headers span the full track set too (grid-column:1/-1), so groups and rows share one geometry. Status badges use color-mix() tints of a single semantic color variable per state (ok/warn/crit), and the live-updating look comes from font-variant-numeric:tabular-nums, which keeps digits from jittering widths when values change — the detail that separates real monitoring UIs from mockups.

Make it yours

  • Add a sparkline column: widen the master template to five tracks — every row inherits it with zero per-row edits.
  • tabular-nums is non-negotiable for live values; pair with text-align:end on the value cell.
  • Semantic state colors are three variables (--ok/--warn/--crit) — map them to your alerting palette.
  • Row density: 40px rows read as ops-tooling; 48px for exec dashboards.

Gotchas — read before shipping

  • Subgrid only inherits tracks from the DIRECT grid parent — the <li> must be a grid item of the <ul> that owns the template.
  • Every subgrid row must span the same track range (grid-column:1/-1) or its children land on partial rails and misalign.
  • Firefox shipped subgrid first (2019); Chrome 117 (2023) completed coverage — but there's no useful fallback except fixed widths, so check your support floor.

Browser support

ChromeSafariFirefoxEdge
117+16+71+117+

Subgrid is universal in evergreen browsers since Sep 2023. Fallback for older: replace subgrid with the same explicit template on each row.

Techniques used in this demo

Search CodeFronts

Loading…