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

App Sidebar Navigation with Integrated Sticky Search Bar

The command-center rail: a search field pinned above a long scrolling menu — sticky INSIDE the sidebar's own scroll context — with a ⌘K keycap hint, a scroll-aware border that appears only once the list has scrolled beneath it, and :focus-within lighting the whole search box when the input takes focus.

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-21">
  <aside class="sbl-21__rail" aria-label="Channels">
    <div class="sbl-21__search">
      <label class="sbl-21__field">
        <svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
        <input type="search" placeholder="Jump to…" aria-label="Search channels">
        <kbd>⌘K</kbd>
      </label>
    </div>
    <nav class="sbl-21__nav">
      <a href="#" aria-current="page"># general</a><a href="#"># announcements</a><a href="#"># engineering</a><a href="#"># design-systems</a><a href="#"># frontend-guild</a><a href="#"># css-wizardry</a><a href="#"># accessibility</a><a href="#"># performance</a><a href="#"># releases</a><a href="#"># random</a><a href="#"># watercooler</a><a href="#"># reading-club</a>
    </nav>
  </aside>
  <main class="sbl-21__main"><h1># general</h1><p>Scroll the channel list — the search stays pinned inside the rail's own scroll context, and channels slide beneath it.</p></main>
</section>
.sbl-21,
.sbl-21 *,
.sbl-21 *::before,
.sbl-21 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sbl-21 {
  --panel: oklch(0.17 0.02 310);
  --ink: oklch(0.94 0.005 310);
  --mut: oklch(0.64 0.014 310);
  --line: oklch(0.28 0.02 310);
  --accent: oklch(0.72 0.15 310);
  display: grid;
  grid-template-columns: 264px 1fr;
  height: 100vh;
  height: 100dvh;
  font-family: system-ui,'Segoe UI',sans-serif;
  background: oklch(0.13 0.015 310);
  color: var(--ink);
}

.sbl-21__rail {
  background: var(--panel);
  border-right: 1px solid var(--line);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.sbl-21__search {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 14px 12px 10px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

.sbl-21__field {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 9px;
  padding: 0 12px;
  height: 40px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: oklch(0.14 0.016 310);
  transition: border-color .2s ease,box-shadow .2s ease;
}

.sbl-21__field:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab,var(--accent) 22%,transparent);
}

.sbl-21__field svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: var(--mut);
  stroke-width: 2;
  stroke-linecap: round;
}

.sbl-21__field input {
  min-width: 0;
  border: none;
  background: none;
  color: var(--ink);
  font: 400 13.5px/1 system-ui,sans-serif;
  outline: none;
}

.sbl-21__field input::placeholder {
  color: color-mix(in oklab,var(--mut) 75%,transparent);
}

.sbl-21__field kbd {
  font: 600 10.5px/1 ui-monospace,Menlo,monospace;
  color: var(--mut);
  background: color-mix(in oklab,var(--ink) 8%,transparent);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 3px 5px;
}

.sbl-21__nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 10px 12px 16px;
}

.sbl-21__nav a {
  padding: 9px 12px;
  border-radius: 9px;
  font: 500 13.5px/1 system-ui,sans-serif;
  color: var(--mut);
  text-decoration: none;
  transition: background-color .15s ease,color .15s ease;
}

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

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

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

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

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

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

@media (prefers-reduced-motion: reduce) {
  .sbl-21__field,
    .sbl-21__nav a {
    transition: none;
  }
}
/* No JavaScript — the search is position:sticky inside the rail's own scroll context; :focus-within ring-lights the whole field when the input focuses. */
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: App Sidebar Navigation with Integrated Sticky Search Bar
Source: https://codefronts.com/layouts/css-sidebar-layouts/search-top-sidebar/

The command-center rail: a search field pinned above a long scrolling menu — sticky INSIDE the sidebar's own scroll context — with a ⌘K keycap hint, a scroll-aware border that appears only once the list has scrolled beneath it, and :focus-within lighting the whole search box when the input takes focus.
## HTML
```html
<section class="sbl-21">
  <aside class="sbl-21__rail" aria-label="Channels">
    <div class="sbl-21__search">
      <label class="sbl-21__field">
        <svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
        <input type="search" placeholder="Jump to…" aria-label="Search channels">
        <kbd>⌘K</kbd>
      </label>
    </div>
    <nav class="sbl-21__nav">
      <a href="#" aria-current="page"># general</a><a href="#"># announcements</a><a href="#"># engineering</a><a href="#"># design-systems</a><a href="#"># frontend-guild</a><a href="#"># css-wizardry</a><a href="#"># accessibility</a><a href="#"># performance</a><a href="#"># releases</a><a href="#"># random</a><a href="#"># watercooler</a><a href="#"># reading-club</a>
    </nav>
  </aside>
  <main class="sbl-21__main"><h1># general</h1><p>Scroll the channel list — the search stays pinned inside the rail's own scroll context, and channels slide beneath it.</p></main>
</section>
```
## CSS
```css
.sbl-21,
.sbl-21 *,
.sbl-21 *::before,
.sbl-21 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sbl-21 {
  --panel: oklch(0.17 0.02 310);
  --ink: oklch(0.94 0.005 310);
  --mut: oklch(0.64 0.014 310);
  --line: oklch(0.28 0.02 310);
  --accent: oklch(0.72 0.15 310);
  display: grid;
  grid-template-columns: 264px 1fr;
  height: 100vh;
  height: 100dvh;
  font-family: system-ui,'Segoe UI',sans-serif;
  background: oklch(0.13 0.015 310);
  color: var(--ink);
}

.sbl-21__rail {
  background: var(--panel);
  border-right: 1px solid var(--line);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.sbl-21__search {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 14px 12px 10px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

.sbl-21__field {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 9px;
  padding: 0 12px;
  height: 40px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: oklch(0.14 0.016 310);
  transition: border-color .2s ease,box-shadow .2s ease;
}

.sbl-21__field:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab,var(--accent) 22%,transparent);
}

.sbl-21__field svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: var(--mut);
  stroke-width: 2;
  stroke-linecap: round;
}

.sbl-21__field input {
  min-width: 0;
  border: none;
  background: none;
  color: var(--ink);
  font: 400 13.5px/1 system-ui,sans-serif;
  outline: none;
}

.sbl-21__field input::placeholder {
  color: color-mix(in oklab,var(--mut) 75%,transparent);
}

.sbl-21__field kbd {
  font: 600 10.5px/1 ui-monospace,Menlo,monospace;
  color: var(--mut);
  background: color-mix(in oklab,var(--ink) 8%,transparent);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 3px 5px;
}

.sbl-21__nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 10px 12px 16px;
}

.sbl-21__nav a {
  padding: 9px 12px;
  border-radius: 9px;
  font: 500 13.5px/1 system-ui,sans-serif;
  color: var(--mut);
  text-decoration: none;
  transition: background-color .15s ease,color .15s ease;
}

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

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

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

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

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

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

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

## JavaScript
```js
/* No JavaScript — the search is position:sticky inside the rail's own scroll context; :focus-within ring-lights the whole field when the input focuses. */
```

How this works

The search box is position:sticky; top:0 — but crucially, sticky is relative to the nearest scrolling ancestor, which here is the sidebar itself (overflow-y:auto), not the page. Sticky-in-a-pane is the underused variant: the pinned search belongs to the rail's scroll context, so page scrolling never affects it. A z-index and matching panel background keep list items sliding cleanly underneath.

The scroll-aware border uses a one-pixel trick: a 1px 'sentinel' div sits above the sticky search; a rule keyed off scroll-state() isn't universal yet, so this demo uses the robust classic — the search box carries a bottom border in transparent that flips visible via animation-timeline:scroll() where supported, else stays always-on (declared as the fallback first). The search field itself is a <label>-wrapped input with an SVG magnifier and a <kbd> shortcut chip; :focus-within on the wrapper ring-lights the entire box — the polished 'the whole control is active' affordance.

Make it yours

  • Wire the real ⌘K with 3 lines of JS (keydown → input.focus()); the chip is honest UI either way.
  • Move the sticky offset down (top:52px) if a workspace switcher sits above the search.
  • Recent-searches dropdown: attach demo 10's popover to the input's wrapper.
  • The scroll-shadow variant: swap the border for a masked box-shadow for a soft elevation cue.

Gotchas — read before shipping

  • Sticky requires the SIDEBAR to be the scroller — if a parent scrolls instead, the search sticks to the wrong context. Check with devtools' scroll badges.
  • Give the sticky box an opaque background; a transparent sticky header shows list items scrolling through it.
  • Don't trap slash-key or ⌘K globally without checking the event target isn't already an input — hijacked keys inside forms are an accessibility complaint.

Browser support

ChromeSafariFirefoxEdge
115+15.4+110+115+

Sticky-in-pane and :focus-within are long-baseline. The scroll-driven border enhancement needs 2023+ Chrome; the fallback border is universal.

Techniques used in this demo

Search CodeFronts

Loading…