Skip to content

Documentation

On this page

Offcanvas

Hidden sidebars using a native <dialog>. Open and close with command / commandfor — no Offcanvas plugin.

Sizes are minified and gzip. A plugin figure includes the Bootstrap runtime that plugin imports. Shipping every plugin is bootstrap.bundle.min.js at 23.3 KB gzip, not the sum of these rows.
What runs it JavaScript
Bootstrap 5.3 Offcanvas plugin (same helpers as Modal) 6.9 KB gzip
This repo dialog with offcanvas placement 0 KB

When those APIs are missing, this page also loads invoker-commands.js (0.8 KB gzip) and dialog-closedby.js (0.5 KB gzip). See Polyfills.

Markup this component accepts. The full inventory is /components.json.
Avoid
  • command works on <button>, not <a href>.
  • A responsive .offcanvas-{sm,md,lg,xl,xxl} stays in the flow above its breakpoint; do not also toggle it there.

How it works

  • command="show-modal" and commandfor="id" replace data-bs-toggle="offcanvas".
  • command="close" replaces data-bs-dismiss="offcanvas".
  • command="show-popover" opens a non-modal panel so the page can still scroll. popover="manual" has no backdrop (data-bs-scroll="true" + data-bs-backdrop="false"). popover="auto" adds a dimmed ::backdrop and light-dismiss (data-bs-scroll="true" with backdrop).
  • The browser draws the backdrop as ::backdrop. Slide animation uses CSS transitions and @starting-style instead of .showing / .show / .hiding.
  • Default modal offcanvas uses closedby="any" so backdrop click and Escape request close. closedby="none" replaces a static backdrop.
  • command works on <button>, not <a href>.
  • Native events on the dialog are close and cancel instead of *.bs.offcanvas.

Offcanvas components

A static example of the offcanvas header and body. This preview is not a dialog — use the live demo to open one.

Offcanvas
Content for the offcanvas goes here. You can place just about any Bootstrap component or custom elements here.
HTML
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvas" aria-labelledby="offcanvasLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasLabel">Offcanvas</h5>
    <button type="button" class="btn-close" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    Content for the offcanvas goes here. You can place just about any Bootstrap component or custom elements here.
  </div>
</div>

Live demo

Use the button to show and hide an offcanvas via command/commandfor on a dialog with the .offcanvas class.

Offcanvas
Some text as placeholder. In real life you can have the elements you have chosen. Like, text, images, lists, etc.
HTML
<button type="button" class="btn btn-primary" command="show-modal" commandfor="offcanvasExample">
  Toggle offcanvas
</button>

<dialog class="offcanvas offcanvas-start" id="offcanvasExample" closedby="any" aria-labelledby="offcanvasExampleLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasExampleLabel">Offcanvas</h5>
    <button type="button" class="btn-close" command="close" commandfor="offcanvasExample" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    Some text as placeholder. In real life you can have the elements you have chosen. Like, text, images, lists, etc.
  </div>
</dialog>

Body scrolling

popover="manual" with command="show-popover" opens a non-modal panel, so the page can still scroll and there is no backdrop.

Offcanvas with body scrolling

Try scrolling the rest of the page to see this option in action.

HTML
<button type="button" class="btn btn-primary" command="show-popover" commandfor="offcanvasScrolling">
  Enable body scrolling
</button>

<dialog popover="manual" class="offcanvas offcanvas-start" id="offcanvasScrolling" aria-labelledby="offcanvasScrollingLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasScrollingLabel">Offcanvas with body scrolling</h5>
    <button type="button" class="btn-close" command="hide-popover" commandfor="offcanvasScrolling" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <p>Try scrolling the rest of the page to see this option in action.</p>
  </div>
</dialog>

Body scrolling and backdrop

popover="auto" keeps page scrolling and paints a dimmed ::backdrop. Clicking the backdrop (light dismiss) closes the panel.

Backdrop with scrolling

Try scrolling the rest of the page to see this option in action.

HTML
<button type="button" class="btn btn-primary" command="show-popover" commandfor="offcanvasWithBothOptions">
  Enable both scrolling & backdrop
</button>

<dialog popover="auto" class="offcanvas offcanvas-start" id="offcanvasWithBothOptions" aria-labelledby="offcanvasWithBothOptionsLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasWithBothOptionsLabel">Backdrop with scrolling</h5>
    <button type="button" class="btn-close" command="hide-popover" commandfor="offcanvasWithBothOptions" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <p>Try scrolling the rest of the page to see this option in action.</p>
  </div>
</dialog>

Static backdrop

closedby="none" prevents closing on backdrop click and Escape. Dismiss with the close control instead.

Offcanvas
I will not close if you click outside of me.
HTML
<button type="button" class="btn btn-primary" command="show-modal" commandfor="staticBackdrop">
  Toggle static offcanvas
</button>

<dialog class="offcanvas offcanvas-start" id="staticBackdrop" closedby="none" aria-labelledby="staticBackdropLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="staticBackdropLabel">Offcanvas</h5>
    <button type="button" class="btn-close" command="close" commandfor="staticBackdrop" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    I will not close if you click outside of me.
  </div>
</dialog>

Dark offcanvas

Set data-bs-theme="dark" on the component (or a parent) instead of the deprecated .text-bg-dark / .btn-close-white utilities.

Offcanvas

Place offcanvas content here.

HTML
<div class="offcanvas offcanvas-start" data-bs-theme="dark" tabindex="-1" id="offcanvasDark" aria-labelledby="offcanvasDarkLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasDarkLabel">Offcanvas</h5>
    <button type="button" class="btn-close" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <p>Place offcanvas content here.</p>
  </div>
</div>

Responsive

Responsive offcanvas classes hide content outside the viewport from a specified breakpoint and down. Above that breakpoint, the contents behave as usual. For example, .offcanvas-lg hides content below lg and shows it above.

Resize your browser to show the responsive offcanvas toggle.
Responsive offcanvas

This is content within an .offcanvas-lg.

HTML
<button type="button" class="btn btn-primary d-lg-none" command="show-modal" commandfor="offcanvasResponsive">
  Toggle offcanvas
</button>

<div class="alert alert-info d-none d-lg-block">Resize your browser to show the responsive offcanvas toggle.</div>

<dialog class="offcanvas-lg offcanvas-end" id="offcanvasResponsive" closedby="any" aria-labelledby="offcanvasResponsiveLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasResponsiveLabel">Responsive offcanvas</h5>
    <button type="button" class="btn-close" command="close" commandfor="offcanvasResponsive" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <p class="mb-0">This is content within an <code>.offcanvas-lg</code>.</p>
  </div>
</dialog>

Placement

There’s no default placement, so you must add .offcanvas-start, .offcanvas-end, .offcanvas-top, or .offcanvas-bottom. Try top, right, and bottom below.

Offcanvas top
...
Offcanvas right
...
Offcanvas bottom
...
HTML
<div class="d-flex flex-wrap gap-2">
  <button type="button" class="btn btn-primary" command="show-modal" commandfor="offcanvasTop">Toggle top offcanvas</button>
  <button type="button" class="btn btn-primary" command="show-modal" commandfor="offcanvasEnd">Toggle right offcanvas</button>
  <button type="button" class="btn btn-primary" command="show-modal" commandfor="offcanvasBottom">Toggle bottom offcanvas</button>
</div>

<dialog class="offcanvas offcanvas-top" id="offcanvasTop" closedby="any" aria-labelledby="offcanvasTopLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasTopLabel">Offcanvas top</h5>
    <button type="button" class="btn-close" command="close" commandfor="offcanvasTop" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    ...
  </div>
</dialog>

<dialog class="offcanvas offcanvas-end" id="offcanvasEnd" closedby="any" aria-labelledby="offcanvasEndLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasEndLabel">Offcanvas right</h5>
    <button type="button" class="btn-close" command="close" commandfor="offcanvasEnd" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    ...
  </div>
</dialog>

<dialog class="offcanvas offcanvas-bottom" id="offcanvasBottom" closedby="any" aria-labelledby="offcanvasBottomLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasBottomLabel">Offcanvas bottom</h5>
    <button type="button" class="btn-close" command="close" commandfor="offcanvasBottom" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    ...
  </div>
</dialog>

Accessibility

A modal <dialog class="offcanvas"> traps focus like a modal. Name it with aria-labelledby on the title.

popover="manual" is not modal: the page still scrolls and focus is not trapped. Give that panel a close control. popover="auto" light-dismisses and still does not trap focus.

Browser support

Three columns, not one baseline. The same row is on the overview.
No script Polyfill No fallback
dialog with .offcanvas-start, -end, -top, or -bottom. The same command and closedby polyfills as the modal. None