30 CSS Sidebar Layouts
13 / 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

Dual Sidebar App Shell Layout with Left Nav and Right Context Panel

The Notion/Discord-class shell: primary navigation on the left, a contextual detail panel on the right, content in the middle — a 3-column grid where the right panel collapses away on narrower viewports (media query) while left nav survives, encoding the real information hierarchy of these products.

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-13">
  <aside class="sbl-13__nav" aria-label="Workspace">
    <div class="sbl-13__ws"><span class="sbl-13__mark" aria-hidden="true">L</span>Loomcraft</div>
    <div class="sbl-13__grp">Projects</div>
    <nav>
      <a href="#" aria-current="page"># brand-refresh <span class="sbl-13__badge">3</span></a>
      <a href="#"># website-v4</a>
      <a href="#"># mobile-app <span class="sbl-13__badge">12</span></a>
    </nav>
    <div class="sbl-13__grp">Team</div>
    <nav><a href="#"># design-crit</a><a href="#"># announcements</a></nav>
  </aside>
  <main class="sbl-13__feed">
    <h1># brand-refresh</h1>
    <p>The center track is <code>minmax(0,1fr)</code> — wide content shrinks and scrolls instead of crushing the context panel. Resize under 1100px: the right panel yields first, the nav survives.</p>
  </main>
  <aside class="sbl-13__ctx" aria-label="Activity">
    <h2>Activity</h2>
    <ol class="sbl-13__timeline">
      <li><span class="sbl-13__avatar" aria-hidden="true">PR</span><div><strong>Priya</strong> shipped the new wordmark<time>2h ago</time></div></li>
      <li><span class="sbl-13__avatar" aria-hidden="true">MW</span><div><strong>Marcus</strong> commented on palette v3<time>4h ago</time></div></li>
      <li><span class="sbl-13__avatar" aria-hidden="true">AO</span><div><strong>Amara</strong> uploaded 6 explorations<time>Yesterday</time></div></li>
    </ol>
  </aside>
</section>
.sbl-13,
.sbl-13 *,
.sbl-13 *::before,
.sbl-13 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sbl-13 {
  --panel: oklch(0.17 0.018 290);
  --ink: oklch(0.93 0.005 290);
  --mut: oklch(0.63 0.012 290);
  --line: oklch(0.28 0.018 290);
  --accent: oklch(0.7 0.16 300);
  display: grid;
  grid-template-columns: 232px minmax(0,1fr) 280px;
  height: 100vh;
  height: 100dvh;
  font-family: system-ui,'Segoe UI',sans-serif;
  background: oklch(0.14 0.014 290);
  color: var(--ink);
}

.sbl-13__nav {
  background: var(--panel);
  border-right: 1px solid var(--line);
  padding: 16px 10px;
  overflow-y: auto;
}

.sbl-13__ws {
  display: flex;
  align-items: center;
  gap: 10px;
  font: 700 14.5px/1 system-ui,sans-serif;
  padding: 2px 10px 16px;
}

.sbl-13__mark {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  font: 700 12px/1 system-ui,sans-serif;
  color: #fff;
  background: linear-gradient(135deg,var(--accent),oklch(0.6 0.18 260));
}

.sbl-13__grp {
  font: 600 10.5px/1 system-ui,sans-serif;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--mut);
  padding: 14px 10px 6px;
}

.sbl-13__nav nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sbl-13__nav nav a {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border-radius: 8px;
  font: 500 13.5px/1 system-ui,sans-serif;
  color: var(--mut);
  text-decoration: none;
  transition: background-color .15s ease,color .15s ease;
}

.sbl-13__nav nav a:hover {
  color: var(--ink);
  background: color-mix(in oklab,var(--ink) 6%,transparent);
}

.sbl-13__nav nav a[aria-current="page"] {
  color: var(--ink);
  background: color-mix(in oklab,var(--accent) 17%,transparent);
}

.sbl-13__nav nav a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.sbl-13__badge {
  margin-left: auto;
  font: 700 10.5px/1 system-ui,sans-serif;
  color: #fff;
  background: var(--accent);
  border-radius: 999px;
  padding: 3px 7px;
}

.sbl-13__feed {
  overflow-y: auto;
  padding: 30px 34px;
}

.sbl-13__feed h1 {
  font: 650 20px/1.2 system-ui,sans-serif;
  margin-bottom: 12px;
}

.sbl-13__feed p {
  font-size: 14px;
  line-height: 1.7;
  color: var(--mut);
  max-width: 60ch;
  text-wrap: pretty;
}

.sbl-13__feed code {
  font: 500 12.5px ui-monospace,Menlo,monospace;
  background: color-mix(in oklab,var(--ink) 9%,transparent);
  padding: 2px 6px;
  border-radius: 5px;
  color: var(--ink);
}

.sbl-13__ctx {
  border-left: 1px solid var(--line);
  background: var(--panel);
  padding: 20px 16px;
  overflow-y: auto;
}

.sbl-13__ctx h2 {
  font: 600 12px/1 system-ui,sans-serif;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--mut);
  margin-bottom: 16px;
}

.sbl-13__timeline {
  list-style: none;
  display: grid;
  gap: 0;
}

.sbl-13__timeline li {
  position: relative;
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 12px;
  padding-bottom: 20px;
}

.sbl-13__timeline li:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 13.5px;
  top: 32px;
  bottom: 2px;
  width: 1px;
  background: var(--line);
}

.sbl-13__avatar {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font: 700 9.5px/1 system-ui,sans-serif;
  color: #fff;
  background: linear-gradient(135deg,oklch(0.6 0.15 300),oklch(0.55 0.15 240));
}

.sbl-13__timeline strong {
  font-weight: 600;
}

.sbl-13__timeline div {
  font: 400 12.5px/1.5 system-ui,sans-serif;
  color: var(--mut);
}

.sbl-13__timeline time {
  display: block;
  font-size: 11px;
  margin-top: 2px;
  color: color-mix(in oklab,var(--mut) 70%,transparent);
}

@media (max-width: 1100px) {
  .sbl-13 {
    grid-template-columns: 232px minmax(0,1fr);
  }

  .sbl-13__ctx {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sbl-13__nav nav a {
    transition: none;
  }
}
/* No JavaScript — a 3-column grid whose center track is minmax(0,1fr) so wide content can't crush the panels; the context panel yields first at 1100px. */
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: Dual Sidebar App Shell Layout with Left Nav and Right Context Panel
Source: https://codefronts.com/layouts/css-sidebar-layouts/dual-sidebar/

The Notion/Discord-class shell: primary navigation on the left, a contextual detail panel on the right, content in the middle — a 3-column grid where the right panel collapses away on narrower viewports (media query) while left nav survives, encoding the real information hierarchy of these products.
## HTML
```html
<section class="sbl-13">
  <aside class="sbl-13__nav" aria-label="Workspace">
    <div class="sbl-13__ws"><span class="sbl-13__mark" aria-hidden="true">L</span>Loomcraft</div>
    <div class="sbl-13__grp">Projects</div>
    <nav>
      <a href="#" aria-current="page"># brand-refresh <span class="sbl-13__badge">3</span></a>
      <a href="#"># website-v4</a>
      <a href="#"># mobile-app <span class="sbl-13__badge">12</span></a>
    </nav>
    <div class="sbl-13__grp">Team</div>
    <nav><a href="#"># design-crit</a><a href="#"># announcements</a></nav>
  </aside>
  <main class="sbl-13__feed">
    <h1># brand-refresh</h1>
    <p>The center track is <code>minmax(0,1fr)</code> — wide content shrinks and scrolls instead of crushing the context panel. Resize under 1100px: the right panel yields first, the nav survives.</p>
  </main>
  <aside class="sbl-13__ctx" aria-label="Activity">
    <h2>Activity</h2>
    <ol class="sbl-13__timeline">
      <li><span class="sbl-13__avatar" aria-hidden="true">PR</span><div><strong>Priya</strong> shipped the new wordmark<time>2h ago</time></div></li>
      <li><span class="sbl-13__avatar" aria-hidden="true">MW</span><div><strong>Marcus</strong> commented on palette v3<time>4h ago</time></div></li>
      <li><span class="sbl-13__avatar" aria-hidden="true">AO</span><div><strong>Amara</strong> uploaded 6 explorations<time>Yesterday</time></div></li>
    </ol>
  </aside>
</section>
```
## CSS
```css
.sbl-13,
.sbl-13 *,
.sbl-13 *::before,
.sbl-13 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sbl-13 {
  --panel: oklch(0.17 0.018 290);
  --ink: oklch(0.93 0.005 290);
  --mut: oklch(0.63 0.012 290);
  --line: oklch(0.28 0.018 290);
  --accent: oklch(0.7 0.16 300);
  display: grid;
  grid-template-columns: 232px minmax(0,1fr) 280px;
  height: 100vh;
  height: 100dvh;
  font-family: system-ui,'Segoe UI',sans-serif;
  background: oklch(0.14 0.014 290);
  color: var(--ink);
}

.sbl-13__nav {
  background: var(--panel);
  border-right: 1px solid var(--line);
  padding: 16px 10px;
  overflow-y: auto;
}

.sbl-13__ws {
  display: flex;
  align-items: center;
  gap: 10px;
  font: 700 14.5px/1 system-ui,sans-serif;
  padding: 2px 10px 16px;
}

.sbl-13__mark {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  font: 700 12px/1 system-ui,sans-serif;
  color: #fff;
  background: linear-gradient(135deg,var(--accent),oklch(0.6 0.18 260));
}

.sbl-13__grp {
  font: 600 10.5px/1 system-ui,sans-serif;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--mut);
  padding: 14px 10px 6px;
}

.sbl-13__nav nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sbl-13__nav nav a {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border-radius: 8px;
  font: 500 13.5px/1 system-ui,sans-serif;
  color: var(--mut);
  text-decoration: none;
  transition: background-color .15s ease,color .15s ease;
}

.sbl-13__nav nav a:hover {
  color: var(--ink);
  background: color-mix(in oklab,var(--ink) 6%,transparent);
}

.sbl-13__nav nav a[aria-current="page"] {
  color: var(--ink);
  background: color-mix(in oklab,var(--accent) 17%,transparent);
}

.sbl-13__nav nav a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.sbl-13__badge {
  margin-left: auto;
  font: 700 10.5px/1 system-ui,sans-serif;
  color: #fff;
  background: var(--accent);
  border-radius: 999px;
  padding: 3px 7px;
}

.sbl-13__feed {
  overflow-y: auto;
  padding: 30px 34px;
}

.sbl-13__feed h1 {
  font: 650 20px/1.2 system-ui,sans-serif;
  margin-bottom: 12px;
}

.sbl-13__feed p {
  font-size: 14px;
  line-height: 1.7;
  color: var(--mut);
  max-width: 60ch;
  text-wrap: pretty;
}

.sbl-13__feed code {
  font: 500 12.5px ui-monospace,Menlo,monospace;
  background: color-mix(in oklab,var(--ink) 9%,transparent);
  padding: 2px 6px;
  border-radius: 5px;
  color: var(--ink);
}

.sbl-13__ctx {
  border-left: 1px solid var(--line);
  background: var(--panel);
  padding: 20px 16px;
  overflow-y: auto;
}

.sbl-13__ctx h2 {
  font: 600 12px/1 system-ui,sans-serif;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--mut);
  margin-bottom: 16px;
}

.sbl-13__timeline {
  list-style: none;
  display: grid;
  gap: 0;
}

.sbl-13__timeline li {
  position: relative;
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 12px;
  padding-bottom: 20px;
}

.sbl-13__timeline li:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 13.5px;
  top: 32px;
  bottom: 2px;
  width: 1px;
  background: var(--line);
}

.sbl-13__avatar {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font: 700 9.5px/1 system-ui,sans-serif;
  color: #fff;
  background: linear-gradient(135deg,oklch(0.6 0.15 300),oklch(0.55 0.15 240));
}

.sbl-13__timeline strong {
  font-weight: 600;
}

.sbl-13__timeline div {
  font: 400 12.5px/1.5 system-ui,sans-serif;
  color: var(--mut);
}

.sbl-13__timeline time {
  display: block;
  font-size: 11px;
  margin-top: 2px;
  color: color-mix(in oklab,var(--mut) 70%,transparent);
}

@media (max-width: 1100px) {
  .sbl-13 {
    grid-template-columns: 232px minmax(0,1fr);
  }

  .sbl-13__ctx {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sbl-13__nav nav a {
    transition: none;
  }
}
```

## JavaScript
```js
/* No JavaScript — a 3-column grid whose center track is minmax(0,1fr) so wide content can't crush the panels; the context panel yields first at 1100px. */
```

How this works

One declaration does the architecture: grid-template-columns:232px minmax(0,1fr) 280px. The minmax(0,1fr) on the middle track is load-bearing — a bare 1fr means minmax(auto,1fr), and 'auto' lets wide content (tables, code blocks, long URLs) blow the track out past the viewport, crushing the right panel. minmax(0,…) lets the middle column actually shrink and its content scroll or truncate. This single fix answers the most-asked grid layout question on Stack Overflow.

The panels encode hierarchy through response: at 1100px the context panel drops (grid-template-columns:232px minmax(0,1fr) + display:none), because context is enhancement; the left nav persists to 800px before it would hand off to a drawer. Both sidebars scroll independently; the right panel demonstrates its genre — an activity feed with hairline-connected avatars — while the left shows nested channel groups with unread badges pinned to the right edge via margin-left:auto.

Make it yours

  • Track widths: 232/280 are the Notion-ish defaults; chat products run narrower left rails (72px icon rail + 240px channel list — see demo 28).
  • Make the right panel user-collapsible with a checkbox + :has() animating the third track to 0px (demo 02's technique, mirrored).
  • Swap breakpoints for container queries if the shell embeds in a resizable workspace.
  • The center pane's max-width:72ch reading column is optional — remove for full-bleed canvases.

Gotchas — read before shipping

  • minmax(0,1fr) on the middle track — without it one wide <pre> destroys the whole layout. This is the demo's most valuable line.
  • Hide the right panel with display:none (not visibility) so its tab stops leave the keyboard order when it's gone.
  • Two independent borders (right of left rail, left of right rail) — don't use one shared border color at reduced contrast; both need 3:1 against both neighbors.

Browser support

ChromeSafariFirefoxEdge
114+17.5+121+114+

Floor set by oklch(), color-mix(), text-wrap as this demo is written. The core technique itself goes back further — Chrome 57+.

Pure baseline grid — the most compatible shell in the collection. The oklch palette needs 2023 engines; hex fallbacks trivially.

Techniques used in this demo

Search CodeFronts

Loading…