Offcanvas
Offcanvas is a panel that slides in from the edge of the screen over the page. It is like a modal, but the panel is attached to an edge and is usually tall. It holds the menu on a phone, a cart, filters. In the admin dashboard it is the main way to hide the sidebar on a narrow screen.
A panel opened by a button
The panel is an offcanvas offcanvas-start block with an id: an offcanvas-header with a title and a close cross, and an offcanvas-body. A button opens it with data-bs-toggle="offcanvas":
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<div style="min-height: 260px">
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebar" aria-controls="sidebar">
Menu
</button>
</div>
<div class="offcanvas offcanvas-start" tabindex="-1" id="sidebar" aria-labelledby="sidebarLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="sidebarLabel">Tasko Admin</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<ul class="nav flex-column">
<li class="nav-item"><a class="nav-link" href="#">Overview</a></li>
<li class="nav-item"><a class="nav-link" href="#">Users</a></li>
<li class="nav-item"><a class="nav-link" href="#">Settings</a></li>
</ul>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>Click "Menu" and a white panel with links slides in from the left while the page dims. It closes with the cross, the Escape key or a click on the dimmed area.
Which side
| Class | Slides in from |
|---|---|
offcanvas-start | The left |
offcanvas-end | The right |
offcanvas-top | The top |
offcanvas-bottom | The bottom |
The data-bs-scroll="true" attribute on the panel lets the page keep scrolling, and data-bs-backdrop="false" removes the dimming.
A menu that is always visible on wide screens
The offcanvas-lg class instead of offcanvas makes the panel responsive: below 992 pixels it is a sliding panel, from 992 it is a regular block in its place. This is exactly what the admin sidebar needs:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<div style="min-height: 260px">
<button class="btn btn-outline-secondary d-lg-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#adminMenu" aria-controls="adminMenu">
Menu
</button>
<div class="offcanvas-lg offcanvas-start" tabindex="-1" id="adminMenu" aria-labelledby="adminMenuLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="adminMenuLabel">Sections</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#adminMenu" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<ul class="nav flex-column">
<li class="nav-item"><a class="nav-link" href="#">Overview</a></li>
<li class="nav-item"><a class="nav-link" href="#">Orders</a></li>
</ul>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>In the narrow preview you only see the "Menu" button, and the panel slides in on click. On a wide screen the button is hidden by d-lg-none, and the links sit right on the page. The same variants exist for other breakpoints: offcanvas-md, offcanvas-xl.
Common mistake
Copying the close cross from a regular panel into a responsive offcanvas-lg one without data-bs-target. A button with data-bs-dismiss="offcanvas" looks for the nearest parent with the offcanvas class, but the responsive panel has a different class, offcanvas-lg, so the cross does nothing. In a responsive panel give the close button data-bs-target="#adminMenu", as in the example above.
To open a panel from code, use bootstrap.Offcanvas.getOrCreateInstance('#sidebar').show().