Skip to main content

Drawer

A panel that slides in from an edge of the screen, built on the native dialog element. Bootstrap 6’s replacement for offcanvas.

Bootstrap’s drawer docs describe the markup and CSS.

Example

Open a drawer with bsDrawerToggle, which also keeps aria-expanded and aria-controls in sync. bsDrawerClose closes the drawer it is in. Modal drawers trap focus, close on Escape and on backdrop clicks, and stop the page from scrolling.

Drawer

Some text as placeholder. In real life you can have the elements you have chosen, like text, images and lists.

HTML
<button type="button" bsButton theme="primary" [bsDrawerToggle]="basicDrawer">Open drawer</button>

<dialog bsDrawer #basicDrawer="bsDrawer" aria-labelledby="basicDrawer-title">
  <div class="drawer-header">
    <h2 class="drawer-title h5" id="basicDrawer-title">Drawer</h2>
    <button type="button" bsCloseButton bsDrawerClose></button>
  </div>
  <div class="drawer-body">
    <p>
      Some text as placeholder. In real life you can have the elements you have chosen, like text,
      images and lists.
    </p>
  </div>
</dialog>

Placement

Set placement to start (the default), end, top, bottom or fullscreen. start and end follow the text direction.

Placement: end

This drawer slides in from the end edge.

<div class="hstack gap-2 flex-wrap">
  @for (p of placements; track p) {
    <button
      type="button"
      bsButton="outline"
      theme="primary"
      (click)="placement.set(p); drawer.show()">
      {{ p }}
    </button>
  }
</div>

<dialog
  bsDrawer
  #drawer="bsDrawer"
  [placement]="placement()"
  aria-labelledby="placement-drawer-title">
  <div class="drawer-header">
    <h2 class="drawer-title h5" id="placement-drawer-title">Placement: {{ placement() }}</h2>
    <button type="button" bsCloseButton bsDrawerClose></button>
  </div>
  <div class="drawer-body">
    <p>This drawer slides in from the {{ placement() }} edge.</p>
  </div>
</dialog>

Body scrolling

Set scroll with [backdrop]="false" to keep the page scrollable and interactive. The drawer then opens without a backdrop and does not trap focus. With a backdrop, the drawer stays modal but the page still scrolls.

Drawer with body scrolling

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

HTML
<button type="button" bsButton theme="primary" [bsDrawerToggle]="scrollDrawer">
  Enable body scrolling
</button>

<dialog
  bsDrawer
  #scrollDrawer="bsDrawer"
  scroll
  [backdrop]="false"
  aria-labelledby="scrollDrawer-title">
  <div class="drawer-header">
    <h2 class="drawer-title h5" id="scrollDrawer-title">Drawer with body scrolling</h2>
    <button type="button" bsCloseButton bsDrawerClose></button>
  </div>
  <div class="drawer-body">
    <p>Try scrolling the rest of the page to see this option in action.</p>
  </div>
</dialog>

Static backdrop

With backdrop="static" the drawer does not close on backdrop clicks. Add [keyboard]="false" to ignore Escape as well.

Drawer

I will not close if you click outside of me.

HTML
<button type="button" bsButton theme="primary" [bsDrawerToggle]="staticDrawer">
  Toggle static drawer
</button>

<dialog bsDrawer #staticDrawer="bsDrawer" backdrop="static" aria-labelledby="staticDrawer-title">
  <div class="drawer-header">
    <h2 class="drawer-title h5" id="staticDrawer-title">Drawer</h2>
    <button type="button" bsCloseButton bsDrawerClose></button>
  </div>
  <div class="drawer-body">
    <p>I will not close if you click outside of me.</p>
  </div>
</dialog>

Responsive

Set responsive to a breakpoint to use Bootstrap’s .lg:drawer style classes: the content is a drawer below the breakpoint and shows inline from it up. An open drawer closes when the viewport grows past the breakpoint.

Responsive drawer

This is content within an .lg:drawer. Resize your browser to see it switch between inline and drawer.

HTML
<button
  type="button"
  bsButton
  theme="primary"
  class="lg:d-none"
  [bsDrawerToggle]="responsiveDrawer">
  Toggle drawer
</button>

<dialog
  bsDrawer
  #responsiveDrawer="bsDrawer"
  placement="end"
  responsive="lg"
  aria-labelledby="responsiveDrawer-title">
  <div class="drawer-header">
    <h2 class="drawer-title h5" id="responsiveDrawer-title">Responsive drawer</h2>
    <button type="button" bsCloseButton bsDrawerClose></button>
  </div>
  <div class="drawer-body">
    <p class="mb-0">
      This is content within an <code>.lg:drawer</code>. Resize your browser to see it switch
      between inline and drawer.
    </p>
  </div>
</dialog>

Opening from code

Call openDrawer() on BsDialogService with a component or template to show a drawer without writing the <dialog> yourself. A template gets the ref as its context, so it can close() with a value, and the ref’s result promise resolves with it. See opening a dialog from code for the options.

Size: Medium

<button type="button" bsButton theme="primary" (click)="choose()">Choose a size</button>
<p class="mt-3 mb-0">Size: {{ size() }}</p>

<ng-template #picker let-drawer>
  <div class="drawer-header">
    <h5 class="drawer-title">Size</h5>
    <button type="button" bsCloseButton bsDrawerClose></button>
  </div>
  <div class="drawer-body">
    <div bsListGroup>
      @for (option of sizes; track option) {
        <button
          type="button"
          bsListGroupItem
          [active]="option === size()"
          (click)="drawer.close(option)">
          {{ option }}
        </button>
      }
    </div>
  </div>
</ng-template>

API

BsDrawer

Selector: dialog[bsDrawer] · Exported as: bsDrawer

Inputs

NameTypeDefaultDescription
placement'start' | 'end' | 'top' | 'bottom' | 'fullscreen''start'Edge the drawer slides in from.
responsive'sm' | 'md' | 'lg' | 'xl' | '2xl' | nullnullShows the content inline from this breakpoint up.
scrollbooleanfalseKeeps the page scrollable while the drawer is open.
openbooleanfalseWhether the drawer is open. Supports [(open)].
backdropboolean | 'static'trueShows a backdrop. static keeps the drawer open on backdrop clicks.
keyboardbooleantrueCloses the drawer on Escape.
animationbooleantrueSlides the drawer in and out.
idstringgeneratedElement id, used by toggles for aria-controls.

Outputs

NameTypeDescription
openChangebooleanEmits when the drawer opens or closes from inside.
shownvoidEmits after the drawer is shown.
hiddenvoidEmits after the drawer is hidden.
dismissed'escape' | 'backdrop'Emits when the user dismisses the drawer.

Methods

NameTypeDescription
show()voidOpens the drawer.
hide()voidCloses the drawer.
toggle()voidToggles the drawer.
isOpenSignal<boolean>Current open state.

BsDrawerToggle

Selector: [bsDrawerToggle]

Inputs

NameTypeDefaultDescription
bsDrawerToggleBsDrawerrequiredThe drawer to open and close.

BsDialogClose

Selector: [bsDrawerClose], [bsDialogClose]