Bootstrap 5 Collapse JS vs Native <details>/<summary>
Uses bootstrap.Collapse — reads scrollHeight to calculate height, sets inline style.height, swaps .collapsing class, waits for transitionend.
Uses <details> / <summary> — browser handles state, accessibility, keyboard support. Zero JavaScript.
<details> element. Zero JS.| Metric | Bootstrap Collapse | Native <details> |
|---|---|---|
| Initialization time (50 instances) | - | - |
| Toggle time (100 cycles × 50 items) | - | - |
| Instance memory cost (50 instances) | - | - |
|
JS code size
collapse.js (8.6 KB)
|
- | - |
|
CSS output size
_transitions.scss (0.4 KB)
|
- | - |
data-bs-toggle="collapse"
<details>/<summary>
scrollHeight, sets inline height, swaps .collapsing class,
waits for transitionend). Native <details> opens instantly by default.
However, native <details> can achieve the same smooth animation
using pure CSS via the ::details-content pseudo-element — zero JavaScript required.
The benchmark above disables all transitions to measure raw JS overhead only.
<details> vs Bootstrap CollapseClick items below to compare the animation feel. Both have a 0.35s ease transition. The native side uses only CSS.
.collapsing + scrollHeight)
scrollHeight to calculate height, sets an inline style.height, adds the .collapsing class, then waits for transitionend to swap to .collapse.show.scrollHeight read), multiple class changes, and inline style mutations.::details-content)
::details-content pseudo-element transitions block-size from 0 to auto. Zero JavaScript. The browser handles everything: state management, accessibility, keyboard support.scrollHeight reads, no forced reflows, no class toggling, no inline styles. The browser’s CSS engine interpolates block-size: 0 → block-size: auto natively.::details-content to match Bootstrap’s animation.details {
/* Required: enables transition between 0 and auto */
interpolate-size: allow-keywords;
}
details::details-content {
transition: block-size 0.35s ease,
content-visibility 0.35s ease allow-discrete;
block-size: 0;
overflow: hidden;
}
details[open]::details-content {
block-size: auto;
}