Bootstrap 5 doesn't ship a sidebar component — you build it yourself with CSS flexbox. The good news is it's straightforward once you understand the three-part structure: wrapper → sidebar → main content.

The Core Layout Structure

Every sidebar layout follows this pattern:

<div class="wrapper d-flex">        <!-- flex container -->
  <aside class="sidebar">           <!-- fixed width -->
    <!-- navigation -->
  </aside>
  <div class="main-content flex-grow-1">  <!-- fills remaining space -->
    <!-- page content -->
  </div>
</div>

1. Basic Sticky Sidebar

A sidebar that sticks while the main content scrolls:

<style>
  body { margin: 0; }

  .sidebar {
    width: 240px;
    min-height: 100vh;
    background: #fff;
    border-right: 1px solid #e5e7eb;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
  }

  .sidebar-brand {
    padding: 16px 20px;
    border-bottom: 1px solid #e5e7eb;
    font-weight: 700;
    color: #fd4766;
    font-size: 1rem;
  }

  .sidebar-nav {
    padding: 8px;
    flex: 1;
  }

  .sidebar-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border-radius: 6px;
    text-decoration: none;
    color: #6b7280;
    font-size: 0.88rem;
    margin-bottom: 2px;
    transition: background 0.15s, color 0.15s;
  }

  .sidebar-link:hover { background: #f3f4f6; color: #111; }
  .sidebar-link.active { background: rgba(253,71,102,0.08); color: #fd4766; font-weight: 600; }

  .sidebar-footer {
    padding: 12px 16px;
    border-top: 1px solid #e5e7eb;
  }

  .main-content {
    flex: 1;
    min-width: 0;
    background: #f8f9fa;
    min-height: 100vh;
  }

  .main-header {
    background: #fff;
    border-bottom: 1px solid #e5e7eb;
    padding: 12px 24px;
    position: sticky;
    top: 0;
    z-index: 10;
  }
</style>

<div class="d-flex">
  <!-- Sidebar -->
  <aside class="sidebar">
    <div class="sidebar-brand">AdminPanel</div>

    <nav class="sidebar-nav">
      <div class="text-uppercase px-2 mb-1"
        style="font-size:0.65rem;color:#9ca3af;letter-spacing:0.08em;font-weight:600;">
        Main
      </div>
      <a href="#" class="sidebar-link active">🏠 Dashboard</a>
      <a href="#" class="sidebar-link">
        📦 Templates
        <span class="badge ms-auto" style="background:#fd4766;font-size:0.62rem;">12</span>
      </a>
      <a href="#" class="sidebar-link">👥 Customers</a>
      <a href="#" class="sidebar-link">📊 Analytics</a>

      <div class="text-uppercase px-2 mb-1 mt-3"
        style="font-size:0.65rem;color:#9ca3af;letter-spacing:0.08em;font-weight:600;">
        Settings
      </div>
      <a href="#" class="sidebar-link">⚙️ Settings</a>
      <a href="#" class="sidebar-link">❓ Help</a>
    </nav>

    <div class="sidebar-footer">
      <div class="d-flex align-items-center gap-2">
        <div class="rounded-circle text-white d-flex align-items-center justify-content-center fw-bold"
          style="width:32px;height:32px;background:#fd4766;font-size:0.72rem;flex-shrink:0;">GS</div>
        <div>
          <p class="fw-semibold mb-0" style="font-size:0.82rem;">Gagan Singh</p>
          <p class="text-muted mb-0" style="font-size:0.7rem;">Founder</p>
        </div>
      </div>
    </div>
  </aside>

  <!-- Main content -->
  <div class="main-content">
    <div class="main-header d-flex align-items-center justify-content-between">
      <h6 class="fw-bold mb-0">Dashboard</h6>
      <a href="https://lettstartdesign.com"
        class="btn btn-sm text-white px-3" style="background:#fd4766;">
        Templates
      </a>
    </div>
    <div class="p-4">
      <p class="text-muted">Main content area. The sidebar stays fixed while this scrolls.</p>
    </div>
  </div>
</div>

2. Collapsible Sidebar

Add a toggle button that narrows the sidebar to icon-only mode:

<style>
  .sidebar-collapsible {
    width: 240px;
    transition: width 0.3s ease;
    overflow: hidden;
    flex-shrink: 0;
  }
  .sidebar-collapsible.collapsed { width: 64px; }
  .sidebar-collapsible .label {
    transition: opacity 0.2s;
    white-space: nowrap;
    overflow: hidden;
  }
  .sidebar-collapsible.collapsed .label { opacity: 0; width: 0; }
  .toggle-btn {
    background: none;
    border: 1px solid #e5e7eb;
    border-radius: 50%;
    width: 24px; height: 24px;
    cursor: pointer;
    font-size: 0.7rem;
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    right: -12px;
    top: 20px;
    background: #fff;
    z-index: 10;
  }
</style>

<div class="d-flex" style="position:relative;">
  <aside class="sidebar-collapsible bg-white border-end" id="collSidebar"
    style="min-height:100vh;position:relative;">

    <button class="toggle-btn" id="toggleBtn"
      onclick="toggleSidebar()">◀</button>

    <div class="px-3 py-3 border-bottom" style="min-height:56px;">
      <div class="d-flex align-items-center gap-2">
        <div class="rounded text-white d-flex align-items-center justify-content-center fw-bold flex-shrink-0"
          style="width:28px;height:28px;background:#fd4766;font-size:0.72rem;">AP</div>
        <span class="fw-bold label" style="color:#fd4766;">AdminPanel</span>
      </div>
    </div>

    <nav class="py-2 px-2">
      <a href="#" class="d-flex align-items-center gap-2 px-2 py-2 rounded text-decoration-none mb-1"
        style="color:#fd4766;background:rgba(253,71,102,0.08);">
        <span class="flex-shrink-0">🏠</span>
        <span class="label">Dashboard</span>
      </a>
      <a href="#" class="d-flex align-items-center gap-2 px-2 py-2 rounded text-decoration-none mb-1 text-muted">
        <span class="flex-shrink-0">📦</span>
        <span class="label">Templates</span>
      </a>
      <a href="#" class="d-flex align-items-center gap-2 px-2 py-2 rounded text-decoration-none mb-1 text-muted">
        <span class="flex-shrink-0">👥</span>
        <span class="label">Customers</span>
      </a>
      <a href="#" class="d-flex align-items-center gap-2 px-2 py-2 rounded text-decoration-none mb-1 text-muted">
        <span class="flex-shrink-0">📊</span>
        <span class="label">Analytics</span>
      </a>
    </nav>
  </aside>

  <div class="flex-grow-1 p-4" style="background:#f8f9fa;min-height:100vh;">
    <p class="text-muted">Click the arrow button to collapse the sidebar.</p>
  </div>
</div>

<script>
  let collapsed = false
  function toggleSidebar() {
    collapsed = !collapsed
    const sidebar = document.getElementById('collSidebar')
    const btn = document.getElementById('toggleBtn')
    sidebar.classList.toggle('collapsed', collapsed)
    btn.textContent = collapsed ? '▶' : '◀'
  }
</script>

3. Responsive: Desktop Sidebar + Mobile Off-Canvas

The production-ready pattern — desktop sidebar plus Bootstrap off-canvas for mobile:

<div class="d-flex">
  <!-- Desktop sidebar: hidden on mobile -->
  <aside class="d-none d-lg-flex flex-column bg-white border-end"
    style="width:240px;min-height:100vh;position:sticky;top:0;height:100vh;overflow-y:auto;flex-shrink:0;">
    <div class="px-4 py-3 border-bottom fw-bold" style="color:#fd4766;">AdminPanel</div>
    <nav class="p-2 flex-grow-1">
      <a href="#" class="d-flex align-items-center gap-2 p-2 rounded text-decoration-none mb-1"
        style="color:#fd4766;background:rgba(253,71,102,0.08);font-size:0.88rem;">
        🏠 Dashboard
      </a>
      <a href="#" class="d-flex align-items-center gap-2 p-2 rounded text-decoration-none mb-1 text-muted"
        style="font-size:0.88rem;">📦 Templates</a>
      <a href="#" class="d-flex align-items-center gap-2 p-2 rounded text-decoration-none mb-1 text-muted"
        style="font-size:0.88rem;">👥 Customers</a>
    </nav>
  </aside>

  <!-- Main area -->
  <div class="flex-grow-1" style="min-width:0;">
    <!-- Mobile header with hamburger -->
    <header class="d-lg-none bg-white border-bottom px-3 py-2 d-flex align-items-center gap-3">
      <button class="btn btn-sm btn-outline-secondary border-0"
        data-bs-toggle="offcanvas" data-bs-target="#mobileSidebar">☰</button>
      <span class="fw-bold" style="color:#fd4766;">AdminPanel</span>
    </header>

    <!-- Page content -->
    <main class="p-4" style="background:#f8f9fa;min-height:100vh;">
      <h5 class="fw-bold mb-3">Dashboard</h5>
      <p class="text-muted">Resize to mobile to see the off-canvas sidebar.</p>
    </main>
  </div>
</div>

<!-- Mobile off-canvas sidebar -->
<div class="offcanvas offcanvas-start" tabindex="-1" id="mobileSidebar" style="width:240px;">
  <div class="offcanvas-header border-bottom">
    <span class="fw-bold" style="color:#fd4766;">AdminPanel</span>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas"></button>
  </div>
  <div class="offcanvas-body p-2">
    <a href="#" class="d-flex align-items-center gap-2 p-2 rounded text-decoration-none mb-1"
      style="color:#fd4766;background:rgba(253,71,102,0.08);font-size:0.88rem;">
      🏠 Dashboard
    </a>
    <a href="#" class="d-flex align-items-center gap-2 p-2 rounded text-decoration-none mb-1 text-muted"
      style="font-size:0.88rem;">📦 Templates</a>
    <a href="#" class="d-flex align-items-center gap-2 p-2 rounded text-decoration-none mb-1 text-muted"
      style="font-size:0.88rem;">👥 Customers</a>
  </div>
</div>

Active Link Highlighting

Add active state with a small JavaScript snippet:

// Highlight current page link
const currentPath = window.location.pathname
document.querySelectorAll('.sidebar-link').forEach(link => {
  if (link.getAttribute('href') === currentPath) {
    link.classList.add('active')
  }
})

Or with data attributes to make it explicit:

<a href="/dashboard" class="sidebar-link" data-path="/dashboard">Dashboard</a>
const path = window.location.pathname
document.querySelectorAll('[data-path]').forEach(el => {
  if (el.dataset.path === path) el.classList.add('active')
})

Dark Sidebar Variant

Swap the sidebar colors for a dark theme:

.sidebar-dark {
  background: #0d0d0d;
  border-right-color: #1e1e2e;
}
.sidebar-dark .sidebar-link { color: #888; }
.sidebar-dark .sidebar-link:hover { background: #1a1a2e; color: #fff; }
.sidebar-dark .sidebar-link.active { background: rgba(253,71,102,0.15); color: #fd4766; }

If you want a production-ready Angular + Bootstrap admin dashboard with a polished sidebar already built, check out the Marvel Angular Dashboard — use code FIRST30 for 30% off.

Frequently Asked Questions

Bootstrap 5 has no built-in sidebar component. Build it with CSS flexbox: a wrapper div with display:flex, a sidebar div with fixed width and min-height:100vh, and a main content div with flex:1. The sidebar sticks with position:sticky and top:0 if you want it fixed while content scrolls.
Set position:sticky; top:0; height:100vh; overflow-y:auto on the sidebar. This keeps it visible while main content scrolls. Make sure no parent element has overflow:hidden — that breaks sticky. Alternatively use position:fixed with matching margin-left on the main content.
Track collapsed state with a boolean. Toggle a CSS class that changes sidebar width: 240px when expanded, 64px when collapsed. Add transition:width 0.3s ease. Conditionally show/hide text labels based on state. Use a toggle button to switch.
Hide the desktop sidebar on mobile with d-none d-lg-flex. Use Bootstrap's off-canvas component for mobile — trigger it with a hamburger button in the top navbar. The off-canvas slides in from the left and shares the same navigation content.

Need a Full Bootstrap 5 Admin Dashboard?

Get a complete Angular 21 + Bootstrap 5 dashboard with 50+ components — built by the same team behind BootstrapPlanet.

Browse Templates →

Use code FIRST30 for 30% off your first purchase.

Related Components