Layout

Bootstrap Sidebar: Responsive, Fixed and Collapsible

By the bootstrap.build team · 5 min read · Published

Bootstrap has no sidebar component, but it has everything you need to build one: the grid or flex utilities for the layout, nav classes for the links, and the offcanvas component for a sidebar that slides in on phones. This guide builds the three sidebars people need most: a fixed sidebar for dashboards and admin panels, a sidebar that turns into an offcanvas menu on small screens, and a collapsible sidebar with grouped links. Everything is for Bootstrap 5.3.

A dashboard layout with a fixed sidebar

The most common layout: a sidebar on the left, the page on the right, and the sidebar hidden behind a menu button on phones.

<div class="d-flex">
  <nav class="offcanvas-lg offcanvas-start d-lg-flex flex-column border-end bg-body-tertiary" id="sidebar"
    tabindex="-1" aria-labelledby="sidebar-title" style="width: 260px;">
    <div class="offcanvas-header">
      <h2 class="offcanvas-title fs-5" id="sidebar-title">Acme</h2>
      <button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#sidebar" aria-label="Close"></button>
    </div>
    <div class="offcanvas-body flex-lg-grow-1 d-flex flex-column p-3">
      <a href="/" class="d-none d-lg-block fs-5 fw-semibold text-body text-decoration-none mb-3">Acme</a>
      <ul class="nav nav-pills flex-column gap-1">
        <li class="nav-item"><a class="nav-link active" aria-current="page" href="/dashboard">Dashboard</a></li>
        <li class="nav-item"><a class="nav-link" href="/orders">Orders</a></li>
        <li class="nav-item"><a class="nav-link" href="/customers">Customers</a></li>
        <li class="nav-item"><a class="nav-link" href="/reports">Reports</a></li>
      </ul>
      <hr>
      <a class="nav-link mt-auto" href="/settings">Settings</a>
    </div>
  </nav>

  <div class="flex-grow-1 min-vh-100">
    <header class="d-lg-none border-bottom p-2">
      <button class="btn btn-outline-secondary" type="button" data-bs-toggle="offcanvas"
        data-bs-target="#sidebar" aria-controls="sidebar">Menu</button>
    </header>
    <main class="p-4">
      <h1 class="h3">Dashboard</h1>
    </main>
  </div>
</div>

How it works:

  • offcanvas-lg makes the sidebar a normal, always-visible element from the lg breakpoint (992px) up, and a slide-in panel below it. Use offcanvas-md or another breakpoint to change where it switches.
  • offcanvas-start slides it in from the left on small screens.
  • The Menu button only shows below lg (d-lg-none) and opens the panel with data-bs-toggle="offcanvas".
  • nav-pills flex-column stacks the links and highlights the active one. aria-current="page" tells screen readers which page is open.
  • mt-auto pushes the Settings link to the bottom of the sidebar. On large screens Bootstrap stops the offcanvas body from growing, so d-lg-flex flex-column on the sidebar and flex-lg-grow-1 on its body are needed for this to work there.

Load bootstrap.bundle.min.js for the offcanvas to work on phones. The style="width: 260px" sets both the sidebar’s width on large screens and the slide-in panel’s width on phones. Without it, the panel is 400px wide, or the full screen width on smaller phones.

To see this sidebar in a full dashboard with stat cards, a chart, and a table, or to compare ready-made admin templates such as AdminLTE and Tabler, read our Bootstrap admin template guide.

Keep the sidebar visible while the page scrolls

Make the sidebar stick to the top of the window on large screens:

@media (min-width: 992px) {
  #sidebar { position: sticky; top: 0; height: 100vh; overflow-y: auto; }
}

The sidebar then stays in place while the main content scrolls, and scrolls on its own if its links don’t fit.

A sidebar with the grid

For a content site, such as documentation with a table of contents, a grid column is simpler:

<div class="container">
  <div class="row">
    <aside class="col-lg-3 d-none d-lg-block">
      <nav class="position-sticky top-0 pt-3" aria-label="Guide sections">
        <ul class="nav flex-column">
          <li class="nav-item"><a class="nav-link px-0" href="#install">Install</a></li>
          <li class="nav-item"><a class="nav-link px-0" href="#usage">Usage</a></li>
          <li class="nav-item"><a class="nav-link px-0" href="#options">Options</a></li>
        </ul>
      </nav>
    </aside>
    <main class="col-lg-9">...</main>
  </div>
</div>

The sidebar takes 3 of the 12 columns on large screens and is hidden on smaller ones. The column classes are explained in the Bootstrap columns guide.

Collapsible groups in the sidebar

For many links, group them under headings that open and close with Bootstrap’s collapse component:

<ul class="nav flex-column">
  <li class="nav-item">
    <button class="btn btn-toggle nav-link d-flex w-100 justify-content-between" type="button"
      data-bs-toggle="collapse" data-bs-target="#reports-links" aria-expanded="true" aria-controls="reports-links">
      Reports <span aria-hidden="true">&#9662;</span>
    </button>
    <div class="collapse show" id="reports-links">
      <ul class="nav flex-column ms-3">
        <li class="nav-item"><a class="nav-link" href="/reports/sales">Sales</a></li>
        <li class="nav-item"><a class="nav-link" href="/reports/traffic">Traffic</a></li>
      </ul>
    </div>
  </li>
</ul>

show opens the group at the start; leave it off for closed groups. To open the group for the current page automatically, add show on the server when one of its links is active.

Icons and a dark sidebar

Add Bootstrap Icons before each link, and make the sidebar dark with data-bs-theme="dark":

<nav class="offcanvas-lg offcanvas-start bg-dark text-body" data-bs-theme="dark" id="sidebar" tabindex="-1">
  <div class="offcanvas-body p-3">
    <ul class="nav nav-pills flex-column gap-1">
      <li class="nav-item">
        <a class="nav-link active d-flex align-items-center gap-2" href="/dashboard" aria-current="page">
          <i class="bi bi-speedometer2" aria-hidden="true"></i> Dashboard
        </a>
      </li>
    </ul>
  </div>
</nav>

data-bs-theme="dark" switches the links and close button to light colors inside the sidebar only. Add text-body so plain text turns light too: on large screens the sidebar otherwise keeps the page’s dark text color. The dark mode guide covers switching the whole page.

An icon-only sidebar on medium screens

A narrow sidebar that shows only icons saves space on tablets:

<nav class="d-none d-md-flex d-lg-none flex-column align-items-center gap-3 border-end py-3" style="width: 64px;">
  <a href="/dashboard" class="link-body-emphasis" aria-label="Dashboard"><i class="bi bi-speedometer2 fs-5"></i></a>
  <a href="/orders" class="link-body-emphasis" aria-label="Orders"><i class="bi bi-receipt fs-5"></i></a>
</nav>

Give each icon link an aria-label, and add a tooltip so sighted users see the label too.

Control the sidebar with JavaScript

const sidebar = bootstrap.Offcanvas.getOrCreateInstance('#sidebar')
sidebar.show()
sidebar.hide()

To close the phone menu after a link is clicked:

document.querySelectorAll('#sidebar .nav-link').forEach(link => {
  link.addEventListener('click', () => bootstrap.Offcanvas.getInstance('#sidebar')?.hide())
})

The offcanvas fires show.bs.offcanvas, shown.bs.offcanvas, hide.bs.offcanvas, and hidden.bs.offcanvas. By default it shows a backdrop, closes on Escape, and locks page scrolling while open; set data-bs-scroll="true" to allow scrolling, or data-bs-backdrop="false" to drop the backdrop.

Common problems

The menu button does nothing. Bootstrap’s JavaScript isn’t loaded, or data-bs-target doesn’t match the sidebar’s id.

The sidebar is hidden on desktop. It uses offcanvas instead of offcanvas-lg. The responsive class keeps it visible from the breakpoint up.

The sidebar is too narrow or too wide. Change the width on the sidebar element, which applies on desktops and phones, or use a grid column for the desktop layout.

Content sits under the sidebar. The layout is missing the d-flex wrapper, so the sidebar and main area aren’t side by side.

FAQ

How do I make a sidebar in Bootstrap 5?

Put a vertical nav (nav flex-column) in an element with the offcanvas-lg offcanvas-start classes, next to your main content inside a d-flex wrapper. It shows as a normal sidebar on large screens and as a slide-in menu on phones, opened by a button with data-bs-toggle="offcanvas".

How do I make a responsive sidebar in Bootstrap?

Use a responsive offcanvas class such as offcanvas-lg. Above the breakpoint the sidebar is always visible; below it, it hides and slides in when a menu button is clicked.

How do I make a fixed sidebar in Bootstrap?

On large screens, give the sidebar position: sticky; top: 0; height: 100vh; overflow-y: auto;. It stays in place while the main content scrolls, and scrolls on its own if needed.

What is offcanvas in Bootstrap?

Offcanvas is a Bootstrap 5 component for a hidden panel that slides in from an edge of the screen, with a backdrop and keyboard support. It’s used for mobile menus, sidebars, filters, and carts.

How do I add a collapsible menu to a Bootstrap sidebar?

Wrap each group of links in a <div class="collapse" id="..."> and toggle it with a button that has data-bs-toggle="collapse" and data-bs-target pointing to that id. Add show to groups that should start open.

Try it in the builder

Make these changes visually with a live preview, then export clean Bootstrap Sass or CSS.

Open the Builder