Offcanvas
Build hidden side panels for navigation, filters, carts, and contextual workflows with captured header and body content.
How it works
- Offcanvas uses the Bootstrap JavaScript plugin to toggle a fixed-position panel into view.
- Only one offcanvas should be visible at a time. The plugin manages the backdrop, focus, and body scroll state while it is open.
- Use
canvas-idon<bs-offcanvas>and point triggers at it withdata-bs-targetorhref. - Offcanvas panels are fixed-position elements that slide in from a configured edge. Avoid margin or transform utilities on the root panel; wrap inner content when extra positioning is needed.
- The slide transition honors Bootstrap's reduced-motion handling.
- The BCL helpers cover the root, header, body, placement, scroll, backdrop options, and title wiring for
aria-labelledby. Responsive variants are currently applied with Bootstrap classes.
Live demo
Use a button or link with data-bs-toggle="offcanvas" and either data-bs-target or href pointing to the generated offcanvas id.
Offcanvas
Panel content can hold navigation, filters, summaries, forms, or any supported Bootstrap content.
- Action queue
- Pending review
- Completed work
<bs-button btn-style="Primary" data-bs-toggle="offcanvas" data-bs-target="#docsOffcanvas" aria-controls="docsOffcanvas">Open offcanvas</bs-button>
<bs-offcanvas canvas-id="docsOffcanvas" placement="Start">
<bs-offcanvas-header off-canvas-title="Offcanvas">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>
<bs-p>Panel content can hold navigation, filters, summaries, forms, or any supported Bootstrap content.</bs-p>
<bs-listgroup>
<bs-listgroup-item>Action queue</bs-listgroup-item>
<bs-listgroup-item>Pending review</bs-listgroup-item>
<bs-listgroup-item>Completed work</bs-listgroup-item>
</bs-listgroup>
</bs-offcanvas-body>
</bs-offcanvas>
Offcanvas components
Review filters
The header title, dismiss button, and body content are independent captures.
<bs-button btn-style="Secondary" data-bs-toggle="offcanvas" data-bs-target="#componentsOffcanvas" aria-controls="componentsOffcanvas">Open component example</bs-button>
<bs-offcanvas canvas-id="componentsOffcanvas" placement="End">
<bs-offcanvas-header off-canvas-title="Review filters">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>
<bs-p>The header title, dismiss button, and body content are independent captures.</bs-p>
<bs-div display="Grid" gap="Default2">
<bs-button btn-style="Primary">Apply filters</bs-button>
<bs-button btn-style="Secondary" outline="true" data-bs-dismiss="offcanvas">Cancel</bs-button>
</bs-div>
</bs-offcanvas-body>
</bs-offcanvas>
Body scrolling
Body scrolling
This panel allows the page behind it to keep scrolling while the backdrop remains visible.
<bs-div display="Flex" gap="Default2" flex-wrap="Wrap">
<bs-button btn-style="Primary" outline="true" data-bs-toggle="offcanvas" data-bs-target="#scrollingOffcanvas" aria-controls="scrollingOffcanvas">Allow body scroll</bs-button>
</bs-div>
<bs-offcanvas canvas-id="scrollingOffcanvas" placement="End" scroll="true">
<bs-offcanvas-header off-canvas-title="Body scrolling">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>
<bs-p>This panel allows the page behind it to keep scrolling while the backdrop remains visible.</bs-p>
</bs-offcanvas-body>
</bs-offcanvas>
Body scrolling and backdrop
Scrolling with backdrop
This panel allows the page behind it to keep scrolling while the backdrop remains visible.
<bs-button btn-style="Primary" outline="true" data-bs-toggle="offcanvas" data-bs-target="#scrollingBackdropOffcanvas" aria-controls="scrollingBackdropOffcanvas">Enable body scrolling and backdrop</bs-button>
<bs-offcanvas canvas-id="scrollingBackdropOffcanvas" placement="End" scroll="true" backdrop="True">
<bs-offcanvas-header off-canvas-title="Scrolling with backdrop">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>
<bs-p>This panel allows the page behind it to keep scrolling while the backdrop remains visible.</bs-p>
</bs-offcanvas-body>
</bs-offcanvas>
Static backdrop
Static backdrop
Clicking the backdrop will not close this panel. Use the close button to dismiss it.
<bs-button btn-style="Primary" outline="true" data-bs-toggle="offcanvas" data-bs-target="#staticOffcanvas" aria-controls="staticOffcanvas">Static backdrop</bs-button>
<bs-offcanvas canvas-id="staticOffcanvas" placement="End" backdrop="Static">
<bs-offcanvas-header off-canvas-title="Static backdrop">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>
<bs-p>Clicking the backdrop will not close this panel. Use the close button to dismiss it.</bs-p>
</bs-offcanvas-body>
</bs-offcanvas>
Placement
Specify placement for top, end, bottom, or start positioning. There is no implicit visual placement beyond Bootstrap's default start-side panel.
Top offcanvas
End offcanvas
Bottom offcanvas
Start offcanvas
<bs-div display="Flex" gap="Default2" flex-wrap="Wrap">
<bs-button btn-style="Secondary" data-bs-toggle="offcanvas" data-bs-target="#topOffcanvas" aria-controls="topOffcanvas">Top</bs-button>
<bs-button btn-style="Secondary" data-bs-toggle="offcanvas" data-bs-target="#endOffcanvas" aria-controls="endOffcanvas">End (right)</bs-button>
<bs-button btn-style="Secondary" data-bs-toggle="offcanvas" data-bs-target="#bottomOffcanvas" aria-controls="bottomOffcanvas">Bottom</bs-button>
<bs-button btn-style="Secondary" data-bs-toggle="offcanvas" data-bs-target="#startOffcanvas" aria-controls="startOffcanvas">Start (left)</bs-button>
</bs-div>
<bs-offcanvas canvas-id="topOffcanvas" placement="Top">
<bs-offcanvas-header off-canvas-title="Top offcanvas">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>Top placement slides down from the top edge.</bs-offcanvas-body>
</bs-offcanvas>
<bs-offcanvas canvas-id="endOffcanvas" placement="End">
<bs-offcanvas-header off-canvas-title="End offcanvas">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>End placement slides in from the inline end edge, usually the right side in left-to-right layouts.</bs-offcanvas-body>
</bs-offcanvas>
<bs-offcanvas canvas-id="bottomOffcanvas" placement="Bottom">
<bs-offcanvas-header off-canvas-title="Bottom offcanvas">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>Bottom placement slides up from the bottom edge.</bs-offcanvas-body>
</bs-offcanvas>
<bs-offcanvas canvas-id="startOffcanvas" placement="Start">
<bs-offcanvas-header off-canvas-title="Start offcanvas">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>Start placement slides in from the inline start edge, usually the left side in left-to-right layouts.</bs-offcanvas-body>
</bs-offcanvas>
Dark offcanvas
Dark offcanvas examples pair dark background and text utilities with a contrasting close button. Prefer a color-mode-aware approach when the panel should track the page theme.
Dark offcanvas
Use color utilities for dark variants and switch the close button to the white variant.
<bs-button btn-style="Dark" data-bs-toggle="offcanvas" data-bs-target="#darkOffcanvas" aria-controls="darkOffcanvas">Open dark offcanvas</bs-button>
<bs-offcanvas canvas-id="darkOffcanvas" placement="Start" bg-color="Dark" bg-contrasts-text="true">
<bs-offcanvas-header off-canvas-title="Dark offcanvas">
<bs-close-button white="true" data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>
<bs-p>Use color utilities for dark variants and switch the close button to the white variant.</bs-p>
</bs-offcanvas-body>
</bs-offcanvas>
Responsive
Responsive offcanvas variants behave like a normal visible block at the configured breakpoint and only use offcanvas behavior below it. Use responsive-breakpoint on the root helper and keep the close button breakpoint in sync.
Responsive offcanvas
This behaves as offcanvas below the large breakpoint and as regular visible content at large widths.
<bs-button btn-style="Primary" display-lg="None" data-bs-toggle="offcanvas" data-bs-target="#responsiveOffcanvas" aria-controls="responsiveOffcanvas">Open responsive offcanvas</bs-button>
<bs-offcanvas canvas-id="responsiveOffcanvas" placement="Start" responsive-breakpoint="Large">
<bs-offcanvas-header off-canvas-title="Responsive offcanvas">
<bs-close-button display-lg="None" data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>
<bs-p>This behaves as offcanvas below the large breakpoint and as regular visible content at large widths.</bs-p>
</bs-offcanvas-body>
</bs-offcanvas>
Accessibility
- Use a visible title in the header. When
off-canvas-titleis present and no explicit accessible name is supplied, BCL wires the root to that title witharia-labelledby. - Include a close button or another clear dismissal action inside the panel.
- Avoid opening offcanvas panels automatically. Let users trigger them intentionally.
- Bootstrap adds dialog behavior and focus handling; keep interactive content ordered logically inside the body.
Usage
Use data attributes for normal toggles, or instantiate the plugin when a workflow needs imperative control. Dismiss actions should use a button or another accessible control with data-bs-dismiss="offcanvas".
Via data attributes
<bs-button btn-style="Primary" data-bs-toggle="offcanvas" data-bs-target="#docsOffcanvas" aria-controls="docsOffcanvas">Open offcanvas</bs-button>
<bs-offcanvas canvas-id="docsOffcanvas" placement="Start">
<bs-offcanvas-header off-canvas-title="Offcanvas" />
<bs-offcanvas-body>Offcanvas body content.</bs-offcanvas-body>
</bs-offcanvas>
Via JavaScript
const offcanvasElement = document.querySelector('#docsOffcanvas');
const offcanvas = bootstrap.Offcanvas.getOrCreateInstance(offcanvasElement, {
backdrop: true,
scroll: false
});
offcanvas.show();
Options
placementmaps tooffcanvas-start,offcanvas-end,offcanvas-top, oroffcanvas-bottom.backdropmaps todata-bs-backdropvaluestrue,false, orstatic.scrollmaps todata-bs-scroll="true".canvas-idwrites the rootidused by triggers.
Methods
const offcanvas = bootstrap.Offcanvas.getOrCreateInstance('#docsOffcanvas');
offcanvas.show();
offcanvas.hide();
offcanvas.dispose();
Events
Events
<bs-button btn-style="Secondary" data-bs-toggle="offcanvas" data-bs-target="#eventOffcanvas" aria-controls="eventOffcanvas">Open event example</bs-button>
<bs-offcanvas canvas-id="eventOffcanvas" placement="End" on-show="console.log('offcanvas show', event.target)" on-shown="console.log('offcanvas shown', event.target)" on-hide="console.log('offcanvas hide', event.target)" on-hidden="console.log('offcanvas hidden', event.target)">
<bs-offcanvas-header off-canvas-title="Events">
<bs-close-button data-bs-dismiss="offcanvas" aria-label="Close" />
</bs-offcanvas-header>
<bs-offcanvas-body>Open and close the panel to inspect offcanvas lifecycle events.</bs-offcanvas-body>
</bs-offcanvas>
on-show, on-shown, on-hide, and on-hidden attributes map to Bootstrap's show.bs.offcanvas, shown.bs.offcanvas, hide.bs.offcanvas, and hidden.bs.offcanvas lifecycle events.
Component coverage
- The root
<bs-offcanvas>,<bs-offcanvas-header>, and<bs-offcanvas-body>tag helpers are dogfooded above, including automatic title id wiring. - Body capture is route-safe because the offcanvas root partial preserves the composer placeholder inside the captured body wrapper.
- Responsive behavior, placement, backdrop, scroll, title wiring, and lifecycle events are represented through helper attributes.