| title | Drawer |
|---|---|
| description | Build hidden sidebars or drawers into your project for navigation, shopping carts, and more with a few classes and our JavaScript plugin. Replaces the old Offcanvas component. |
| toc | true |
| css_layer | components |
| css_media | viewport |
| js | required |
Drawer builds on the native <dialog> element and our Dialog component to manage hidden sidebars via JavaScript. These sidebars, or drawers, can appear from the left, right, top, or bottom edge of the viewport. Buttons or anchors are used as triggers that are attached to specific elements you toggle, and data attributes are used to invoke our JavaScript.
- Drawer shares the same base as our Dialog component, using native
<dialog>APIs for focus trapping, backdrop, and top-layer rendering. - Use the
<dialog>element, not a<div>. Due to how CSS handles animations, don’t applymarginortranslatedirectly to.drawer— wrap it if you need those. - Modal by default, or scroll-through — the default opens the drawer modally with a backdrop; set
scroll: trueto render without a backdrop and without locking body scroll. - Built-in backdrop via
::backdrop(modal only) closes the drawer on click; setbackdrop: "static"to lock clicks outside, orbackdrop: falseto hide it. - Escape key handling closes the drawer by default; set
keyboard: falseto disable. - Swipe to dismiss — drawer auto-wires a placement-aware swipe (swipe left to close
drawer-startin LTR, swipe down to closedrawer-bottom, etc.). - Responsive placement —
.sm:drawer,.md:drawer, and up stay drawer-like below their breakpoint and collapse inline above it, making drawers useful as responsive navbars. - Only one drawer can be shown at a time (enforced by the data API).
- Animated open and close — drawer slides back out to its placement-specific off-screen position on close, with the
::backdropfading alongside it when opened modally. When authoring custom CSS, qualify your[open]rules with:not(.hiding)so the exit transition can fall through to the base state; add.drawer-instantto skip animations.
Below is a drawer example that is shown by default (via open and .show on the <dialog>). Drawer includes support for a header with a close button and an optional body class for some initial padding. We suggest that you include drawer headers with dismiss actions whenever possible, or provide an explicit dismiss action.
<Example class="bd-example-drawer p-0 bg-1 overflow-hidden" code={`
Use the buttons below to show and hide a drawer element via JavaScript. You can use a link with the href attribute, or a button with the data-bs-target attribute. In both cases, the data-bs-toggle="drawer" is required.
<Example code={` Link with href Button with data-bs-target
Scrolling the <body> element is disabled when a drawer and its backdrop are visible. Use the data-bs-scroll attribute to enable <body> scrolling.
<Example code={`Enable body scrolling
Try scrolling the rest of the page to see this option in action.
You can also enable <body> scrolling with a visible backdrop.
<Example code={`Enable both scrolling & backdrop
Try scrolling the rest of the page to see this option in action.
When backdrop is set to static, the drawer will not close when clicking outside of it.
<Example code={` Toggle static drawer
By default, drawers animate with a slide on open and close. To disable animations, add .drawer-instant to the <dialog> element.
<Example code={` Toggle instant drawer
This drawer doesn’t animate and appears instantly on open and close.
Change the appearance of drawers with utilities to better match them to different contexts like dark navbars. Here we add data-bs-theme="dark" to the .drawer, and it makes all nested elements within use dark mode.
<Example class="bd-example-drawer p-0 bg-1 overflow-hidden" code={`
Place drawer content here.
Add .drawer-translucent to the drawer panel to blur and saturate the background. This makes the panel semi-transparent so content behind it shows through.
<Example code={` Toggle translucent drawer
Add .drawer-sheet to render the panel flush against the viewport edge. The sheet variant removes the drawer’s inset, border, border-radius, and box-shadow, so it sits edge-to-edge like a traditional offcanvas. It works with any placement: combine it with .drawer-bottom/.drawer-top for a full-bleed panel capped by --drawer-sheet-width, or with .drawer-start/.drawer-end for a full-bleed panel capped by --drawer-sheet-height.
<Example code={` Toggle sheet drawer
.drawer-sheet also works with .drawer-end (or .drawer-start), pinning the panel flush against the right (or left) edge of the viewport instead:
<Example code={` Toggle sheet drawer
Responsive drawer classes hide content outside the viewport from a specified breakpoint and down. Above that breakpoint, the contents within will behave as usual. For example, .lg:drawer hides content in a drawer below the lg breakpoint, but shows the content above the lg breakpoint. Responsive drawer classes are available for each breakpoint.
To make a responsive drawer, replace the .drawer base class with a responsive variant and ensure your close button has an explicit data-bs-target.
<Example code={`Toggle drawer
Resize your browser to show the responsive drawer toggle.
This is content within an .lg:drawer.
There’s no default placement for drawer components, so you must add one of the modifier classes below.
.drawer-startplaces drawer on the left of the viewport (shown above).drawer-endplaces drawer on the right of the viewport.drawer-topplaces drawer on the top of the viewport.drawer-bottomplaces drawer on the bottom of the viewport.drawer-fullscreencovers the entire viewport
Try the top, right, bottom, and fullscreen examples out below.
<Example code={`Toggle top drawer
<Example code={`Toggle right drawer
<Example code={`Toggle bottom drawer
<Example code={`Toggle fullscreen drawer
This drawer covers the entire viewport, useful for full-page menus or modal-like experiences.
Add an optional .drawer-footer for action buttons or other content at the bottom of the drawer.
<Example class="bd-example-drawer p-0 bg-1 overflow-hidden" code={`
Content for the drawer goes here. The footer will stick to the bottom.
Since the drawer panel is built on the native <dialog> element, it inherently has the correct dialog role and modal semantics. Be sure to add aria-labelledby="..."—referencing the drawer title—to the <dialog> element.
Tokens for the drawer backdrop are available in a separate map as they style the native ::backdrop pseudo-element.
The drawer plugin is built on the native <dialog> element and utilizes a few classes and attributes to handle the heavy lifting:
.draweron a<dialog>element enables drawer behavior.drawer-startplaces the drawer on the left.drawer-endplaces the drawer on the right.drawer-topplaces the drawer on the top.drawer-bottomplaces the drawer on the bottom
Add a dismiss button with the data-bs-dismiss="drawer" attribute, which triggers the JavaScript functionality. Be sure to use the <button> element with it for proper behavior across all devices.
Add data-bs-toggle="drawer" and a data-bs-target or href to the element to automatically assign control of one drawer element. The data-bs-target attribute accepts a CSS selector to apply the drawer to. Be sure to use a <dialog> element with the class drawer.
Enable manually with:
const drawerElementList = document.querySelectorAll('dialog.drawer')
const drawerList = [...drawerElementList].map(drawerEl => new bootstrap.Drawer(drawerEl))Activates your content as a drawer element. Accepts an optional options object.
You can create a drawer instance with the constructor, for example:
const bsDrawer = new bootstrap.Drawer('#myDrawer')Bootstrap’s drawer class exposes a few events for hooking into drawer functionality.
| Event type | Description | | --- | --- | | `hide.bs.drawer` | This event is fired immediately when the `hide` method has been called. | | `hidden.bs.drawer` | This event is fired when a drawer element has been hidden from the user (will wait for CSS transitions to complete). | | `hidePrevented.bs.drawer` | This event is fired when the drawer is shown, its backdrop is `static` and a click outside of the drawer is performed. The event is also fired when the escape key is pressed and the `keyboard` option is set to `false`. | | `show.bs.drawer` | This event fires immediately when the `show` instance method is called. | | `shown.bs.drawer` | This event is fired when a drawer element has been made visible to the user (will wait for CSS transitions to complete). |const myDrawer = document.getElementById('myDrawer')
myDrawer.addEventListener('hidden.bs.drawer', event => {
// do something...
})