Offcanvas Benchmark

Bootstrap 5 Offcanvas JS vs Native <dialog> element

Bootstrap JS

Uses bootstrap.Offcanvas — creates backdrop divs, manages focus traps, toggles scroll locks via JavaScript.

Native Browser API

Uses dialog.showModal() / dialog.close() — browser handles backdrop, focus trap, and scroll lock natively. Zero JS dependencies.

Initializing... 0%

Results

Metric Bootstrap Offcanvas Native <dialog>
Initialization time - -
Toggle time (500 open/close cycles) - -
Instance memory cost - -
JS code size
offcanvas.js (8.1 KB) + backdrop.js (4.0 KB) + focustrap.js (3.4 KB) + scrollbar.js (4.6 KB)
- -
CSS output size
_offcanvas.scss (4.7 KB)
- -

Live Example: Animated Native <dialog> vs Bootstrap Offcanvas

Click the buttons below to compare the animation feel. Both slide in from the left with a 0.3s ease transition. The native side uses only CSS.

Bootstrap JS JS animation (backdrop div + CSS transform)
Native Browser API CSS-only animation (@starting-style + transition)
About animation: Bootstrap Offcanvas animates open/close using JavaScript (creates a backdrop <div>, manages focus trap, toggles scroll lock, applies CSS transforms via .offcanvas.showing / .offcanvas.hiding classes). Native <dialog> opens instantly by default. However, native <dialog> can achieve the same smooth slide-in animation using pure CSS via @starting-style and transitionzero JavaScript required. The benchmark above disables all transitions to measure raw JS overhead only.
Native dialog offcanvas — entire implementation
HTML
<!-- Native dialog styled as offcanvas (Bootstrap utility classes) -->
<dialog class="animated-offcanvas position-fixed top-0 start-0 bottom-0
               m-0 h-100 border-0 p-0 bg-white shadow-lg"
        style="width: 400px; max-height: 100dvh;"
        id="myDialog">
  <div class="d-flex align-items-center p-3 border-bottom">
    <h5 class="mb-0 me-auto">Title</h5>
    <button class="btn-close" onclick="myDialog.close()"></button>
  </div>
  <div class="p-3 overflow-auto flex-grow-1">
    Content here...
  </div>
</dialog>

<!-- Open: myDialog.showModal()  Close: myDialog.close() -->
CSS (only display state + slide-in animation)
dialog.animated-offcanvas[open] {
  display: flex;
  flex-direction: column;
}
/* Slide-in from left, same as Bootstrap offcanvas */
dialog.animated-offcanvas {
  transition: translate 0.3s ease,
              display 0.3s ease allow-discrete,
              overlay 0.3s ease allow-discrete;
  translate: -100% 0;
}
dialog.animated-offcanvas[open] { translate: 0 0; }
@starting-style {
  dialog.animated-offcanvas[open] { translate: -100% 0; }
}
/* Backdrop fade */
dialog.animated-offcanvas::backdrop {
  transition: background-color 0.3s ease,
              display 0.3s ease allow-discrete,
              overlay 0.3s ease allow-discrete;
  background-color: transparent;
}
dialog.animated-offcanvas[open]::backdrop {
  background-color: rgba(0, 0, 0, 0.5);
}
@starting-style {
  dialog.animated-offcanvas[open]::backdrop {
    background-color: transparent;
  }
}
Bootstrap Offcanvas

This panel is rendered by Bootstrap’s Offcanvas JS plugin.

It creates a backdrop <div>, activates a JavaScript focus trap, and disables body scroll via ScrollBarHelper.

Bootstrap Offcanvas

This panel uses Bootstrap’s JavaScript Offcanvas plugin.

Each open/close triggers:

Native <dialog>

This panel is a native <dialog> element styled as an offcanvas.

The browser provides backdrop (::backdrop), focus trapping, and scroll lock — all natively, zero JavaScript.

Native <dialog> (Animated)

This panel is a native <dialog> with a pure CSS slide-in animation.

Zero JavaScript for animation. The browser handles:

Total JS: 3 lines (open, close, backdrop click). No framework, no dependencies.