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

Pure CSS Resizable Sidebar Layout Using Resize Property

A drag-to-resize sidebar with no mousemove listeners, no pointer capture, no drag math: the CSS resize property does the entire interaction. min/max-width fence the range, a styled grip zone signals the affordance, and the main pane reflows live because the layout is plain flex — the browser is running the drag loop for you, off the main thread.

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-27">
  <aside class="sbl-27__rail" aria-label="Notes">
    <div class="sbl-27__inner">
      <h2>Notebook</h2>
      <nav>
        <a href="#" aria-current="page">Container queries field guide</a><a href="#">Subgrid recipes</a><a href="#">The :has() cookbook</a><a href="#">Anchor positioning notes</a><a href="#">View transitions research</a>
      </nav>
    </div>
    <span class="sbl-27__grip" aria-hidden="true"><i></i><i></i><i></i></span>
  </aside>
  <main class="sbl-27__main"><h1>Container queries field guide</h1><p>Drag the sidebar's bottom-right corner (or along the dotted grip) — resize:horizontal + a min/max fence, zero drag JavaScript. The pane you're reading reflows live.</p></main>
</section>
.sbl-27,
.sbl-27 *,
.sbl-27 *::before,
.sbl-27 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sbl-27 {
  --panel: oklch(0.17 0.014 85);
  --ink: oklch(0.94 0.006 85);
  --mut: oklch(0.66 0.015 85);
  --line: oklch(0.29 0.018 85);
  --accent: oklch(0.8 0.13 90);
  display: flex;
  height: 100vh;
  height: 100dvh;
  font-family: system-ui,'Segoe UI',sans-serif;
  background: oklch(0.13 0.012 85);
  color: var(--ink);
}

.sbl-27__rail {
  position: relative;
  resize: horizontal;
  overflow: auto;
  min-width: 200px;
  max-width: 440px;
  width: 280px;
  flex: none;
  background: var(--panel);
  border-right: 1px solid var(--line);
}

.sbl-27__inner {
  padding: 20px 14px;
  min-width: 186px;
}

.sbl-27__rail h2 {
  font: 700 14.5px/1 system-ui,sans-serif;
  padding: 0 10px 14px;
}

.sbl-27__rail nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sbl-27__rail a {
  padding: 10px 12px;
  border-radius: 9px;
  font: 500 13.5px/1.35 system-ui,sans-serif;
  color: var(--mut);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background-color .15s ease,color .15s ease;
}

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

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

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

.sbl-27__grip {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 14px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: center;
  justify-content: center;
  cursor: col-resize;
  opacity: .5;
  transition: opacity .2s ease;
}

.sbl-27__grip:hover {
  opacity: 1;
}

.sbl-27__grip i {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--mut);
}

.sbl-27__main {
  flex: 1;
  min-width: 0;
  padding: 32px;
  overflow-y: auto;
}

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

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

@media (pointer: coarse) {
  .sbl-27__grip {
    width: 22px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sbl-27__grip,
    .sbl-27__rail a {
    transition: none;
  }
}
/* No JavaScript — resize:horizontal + overflow:auto + a min/max-width fence; the browser runs the entire drag interaction natively. */
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: Pure CSS Resizable Sidebar Layout Using Resize Property
Source: https://codefronts.com/layouts/css-sidebar-layouts/resizable-sidebar/

A drag-to-resize sidebar with no mousemove listeners, no pointer capture, no drag math: the CSS resize property does the entire interaction. min/max-width fence the range, a styled grip zone signals the affordance, and the main pane reflows live because the layout is plain flex — the browser is running the drag loop for you, off the main thread.
## HTML
```html
<section class="sbl-27">
  <aside class="sbl-27__rail" aria-label="Notes">
    <div class="sbl-27__inner">
      <h2>Notebook</h2>
      <nav>
        <a href="#" aria-current="page">Container queries field guide</a><a href="#">Subgrid recipes</a><a href="#">The :has() cookbook</a><a href="#">Anchor positioning notes</a><a href="#">View transitions research</a>
      </nav>
    </div>
    <span class="sbl-27__grip" aria-hidden="true"><i></i><i></i><i></i></span>
  </aside>
  <main class="sbl-27__main"><h1>Container queries field guide</h1><p>Drag the sidebar's bottom-right corner (or along the dotted grip) — resize:horizontal + a min/max fence, zero drag JavaScript. The pane you're reading reflows live.</p></main>
</section>
```
## CSS
```css
.sbl-27,
.sbl-27 *,
.sbl-27 *::before,
.sbl-27 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sbl-27 {
  --panel: oklch(0.17 0.014 85);
  --ink: oklch(0.94 0.006 85);
  --mut: oklch(0.66 0.015 85);
  --line: oklch(0.29 0.018 85);
  --accent: oklch(0.8 0.13 90);
  display: flex;
  height: 100vh;
  height: 100dvh;
  font-family: system-ui,'Segoe UI',sans-serif;
  background: oklch(0.13 0.012 85);
  color: var(--ink);
}

.sbl-27__rail {
  position: relative;
  resize: horizontal;
  overflow: auto;
  min-width: 200px;
  max-width: 440px;
  width: 280px;
  flex: none;
  background: var(--panel);
  border-right: 1px solid var(--line);
}

.sbl-27__inner {
  padding: 20px 14px;
  min-width: 186px;
}

.sbl-27__rail h2 {
  font: 700 14.5px/1 system-ui,sans-serif;
  padding: 0 10px 14px;
}

.sbl-27__rail nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sbl-27__rail a {
  padding: 10px 12px;
  border-radius: 9px;
  font: 500 13.5px/1.35 system-ui,sans-serif;
  color: var(--mut);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background-color .15s ease,color .15s ease;
}

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

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

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

.sbl-27__grip {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 14px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: center;
  justify-content: center;
  cursor: col-resize;
  opacity: .5;
  transition: opacity .2s ease;
}

.sbl-27__grip:hover {
  opacity: 1;
}

.sbl-27__grip i {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--mut);
}

.sbl-27__main {
  flex: 1;
  min-width: 0;
  padding: 32px;
  overflow-y: auto;
}

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

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

@media (pointer: coarse) {
  .sbl-27__grip {
    width: 22px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sbl-27__grip,
    .sbl-27__rail a {
    transition: none;
  }
}
```

## JavaScript
```js
/* No JavaScript — resize:horizontal + overflow:auto + a min/max-width fence; the browser runs the entire drag interaction natively. */
```

How this works

Three declarations create the interaction: resize:horizontal; overflow:auto (resize only activates on elements with non-visible overflow) and the fence — min-width:200px; max-width:440px. The user drags the bottom-right handle and the browser does hit-testing, cursor, drag tracking and relayout natively. The main pane is flex:1, so it absorbs every width change in the same frame.

The stock handle is a tiny corner triangle, so the demo builds a visible affordance: a full-height grip strip on the sidebar's right edge (three dots, cursor:col-resize) that visually extends the native handle's hit area. Honest limitation, documented: the native handle remains the true drag target at the bottom-right corner — for a full-edge drag you graduate to ~15 lines of pointer-event JS. In exchange, this version costs zero script, works with the keyboard in some browsers, and can't ever leak a stuck-drag state. A @media (pointer:coarse) rule widens the grip on touch devices.

Make it yours

  • The fence IS the design: min 200px keeps nav labels whole; max 440px stops the sidebar from eating the app.
  • Persist the chosen width with a ResizeObserver + localStorage (6 lines) if users expect it remembered.
  • resize:vertical on horizontal split panes (bottom terminals, log viewers) — the same three declarations rotated.
  • Style the corner handle itself in WebKit via ::-webkit-resizer for a brand-colored grip.

Gotchas — read before shipping

  • resize does nothing without overflow set — overflow:auto (or hidden/scroll) is half the feature and everyone forgets it.
  • The element resizes its CONTENT BOX: with border-box sizing, min/max include padding — plan the fence values accordingly.
  • Firefox and Chrome disagree on handle placement in RTL contexts; test if you ship RTL.

Browser support

ChromeSafariFirefoxEdge
114+17.5+121+114+

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

resize is fifteen years old and universal on desktop. It's inert on touch-only devices — the JS upgrade path is the answer where touch resize is a requirement.

Techniques used in this demo

Search CodeFronts

Loading…