mrkeyoor.com_
Wed 23 Sept 02:49 UTC
npmWeb Frontendupdated 22 Sept 2026

bootstrap review

Bootstrap 5.3.8 gives server-rendered pages a responsive grid, utility classes, styled forms, and browser components such as modals, dropdowns, collapse panels, toasts, and offcanvas menus. The CSS works without a JavaScript framework; interactive pieces use Bootstrap's own DOM plugins and `data-bs-*` attributes. This patch fixes WCAG 2.1 behavior in the Sass `color-contrast()` function and stops flex layouts from distorting spinners with multiline content. Our browser build measured 79.9 KB minified and 24 KB gzipped when importing the package namespace.

Verdict

Bootstrap 5.3.8 installed in 1.3 seconds with 0 audit findings, but our full browser import still weighed 79.9 KB minified and 24 KB gzipped. Install it for conventional server-rendered interfaces that benefit from its complete component vocabulary; skip it when a small utility layer or framework-native component kit already covers the job.

We installed it

Lab card: what happened when we installed bootstrapScreenshot of bootstrap documentation
Install✓ · 1.3s2 packages on disk · 13 MB
ImportESM import fails · require() fails · CommonJS package
Browser24 KBgzipped (79.9 KB minified), bundled with esbuild
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does bootstrap install cleanly?

Yes. In a fresh container with an empty cache, npm install bootstrap finished in 1 seconds, leaving 2 packages and 13 MB on disk. npm audit reported no known vulnerabilities.

How much does bootstrap add to a browser bundle?

24 KB gzipped (79.9 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does bootstrap work with both ESM and CommonJS?

Neither plain import nor require succeeded in our sandbox, so it needs a bundler or extra setup.

Does bootstrap include TypeScript types?

No type declarations were found in our install, so TypeScript users need their own declarations.

bootstrap or bulma: which should you use?

bulma: Choose it when component styling should remain CSS-only and your application will own every interactive state. Bootstrap 5.3.8 installed in 1.3 seconds with 0 audit findings, but our full browser import still weighed 79.9 KB minified and 24 KB gzipped.

When should you not use bootstrap?

A product must look unlike Bootstrap. Its spacing, breakpoints, component markup, and state classes spread through HTML, so replacing the visual grammar takes more than changing variables.

API stability4/5Version 5.3.8 retains the 5.x class vocabulary, `data-bs-*` attributes, plugin constructors, and namespaced browser events. The project publishes versioned documentation for older lines, which makes maintenance less dependent on current examples. A major upgrade still reaches deeply into templates: the move to 5 removed jQuery, renamed data attributes, and changed utilities and markup. Because those contracts live in HTML and Sass as well as JavaScript, they cannot be hidden behind one adapter.
Docs5/5The 5.3 documentation separates layout, utilities, forms, Sass customization, color modes, accessibility, and each JavaScript plugin. Examples expose the required markup and data attributes, while migration pages identify changed classes and behavior. Important constraints are sometimes local to a component page: tooltips are opt-in, modal labels remain the author's job, and Sass imports are order-sensitive. Copying the first example without reading those notes can leave behavior or accessibility unfinished.
Maintenance5/5GitHub showed a push on August 25, 2026, 231 open issues and pull requests, and an unarchived repository. Release 5.3.8 fixed WCAG 2.1 handling in `color-contrast()` and spinner distortion in multiline flex layouts, alongside documentation and build work. The repository keeps tests for JavaScript changes and maintains an explicit `v4-dev` branch for Bootstrap 4. That evidence supports active upkeep without treating the open count as issue-only.
Ecosystem5/5The npm download endpoint counted 6,462,713 downloads for August 18 through 24, 2026, and GitHub reported 174,652 stars. The README lists npm, Yarn, Bun, Composer, NuGet, RubyGems, CDN files, and downloadable builds. Templates and third-party framework wrappers are easy to find, but the core project remains HTML, CSS, and imperative JavaScript. React and Vue teams must choose and assess a separate wrapper or manage plugin lifecycles themselves.

Use it if

  • A server-rendered admin panel needs a grid, forms, navigation, dialogs, and responsive utilities without adopting React or Vue.
  • Your team is comfortable putting framework classes in templates and values consistent screens more than a unique visual system.
  • You want compiled CSS for static pages now, with dropdowns, modals, or offcanvas behavior added only where needed.
  • Existing staff and templates already use Bootstrap 5 conventions such as `container`, `row`, breakpoints, and `data-bs-*` controls.
Skip it if

Setup reality

We installed bootstrap 5.3.8 in a fresh Node 22 Bookworm container in 1.3 seconds. The install left 2 packages and 13 MB on disk, and npm audit reported 0 known vulnerabilities. Bootstrap declares no direct dependencies and one peer dependency, @popperjs/core; the package itself is 9980 KB unpacked and has no TypeScript declarations.

The package identifies as CommonJS and has no exports map, yet both require('bootstrap') and ESM import('bootstrap') failed under Node 22.23.2 in our sandbox. That is a server-side loading result, not a browser failure. Import explicit browser files such as bootstrap/dist/css/bootstrap.min.css and the bundled JavaScript, or load a specific plugin module through your bundler. Our full namespace browser build came to 79.9 KB minified and 24 KB gzipped.

Dropdowns, tooltips, and popovers need Popper. The bootstrap.bundle files include it; individual or non-bundle imports need the peer installed and resolved. Grid, spacing, forms, and static cards need no JavaScript. Collapse, modal, offcanvas, toast, and dropdown state do. Tooltips and popovers also require explicit initialization, so their data attributes alone produce nothing.

Sass overrides must appear after functions are imported but before Bootstrap consumes its variables and maps. Color modes switch Bootstrap variables with data-bs-theme; custom colors and third-party widgets still need matching dark styles. The package ships separate RTL CSS. In applications that replace DOM nodes, call a plugin instance's dispose() before removal so Bootstrap does not retain listeners or references.

Patterns

Start with the compiled CDN files cdn-starter

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">

<main class="container py-4">
  <h1>Hello</h1>
</main>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>

Version 5.3.8's bundle includes Popper. Copy the current integrity and crossorigin attributes from the official quick-start page before deploying CDN tags.

Load every compiled component through npm npm-global-import

import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.bundle.min.js';

This path loads all component behavior. A page using only the grid, utilities, or styled forms can omit the second import.

Instantiate only the modal plugin import-one-plugin

import 'bootstrap/dist/css/bootstrap.min.css';
import Modal from 'bootstrap/js/dist/modal';

const element = document.querySelector('#confirm-modal');
const modal = Modal.getOrCreateInstance(element, { keyboard: true });
modal.show();

Direct plugin imports avoid the all-in-one entry. Dropdown, tooltip, and popover modules still resolve the `@popperjs/core` peer.

Change card columns at two breakpoints responsive-grid

<div class="container">
  <div class="row g-3">
    <div class="col-12 col-md-6 col-xl-4"><article class="card p-3">A</article></div>
    <div class="col-12 col-md-6 col-xl-4"><article class="card p-3">B</article></div>
    <div class="col-12 col-md-6 col-xl-4"><article class="card p-3">C</article></div>
  </div>
</div>

The unprefixed 12-column rule applies first. `md` and `xl` replace it only after their documented minimum widths.

Wire a navbar toggle to its collapse target responsive-navbar

<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="/">Acme</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#main-nav" aria-controls="main-nav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="main-nav">
      <a class="nav-link" href="/docs">Docs</a>
    </div>
  </div>
</nav>

Collapse needs Bootstrap JavaScript. The selector in `data-bs-target`, the target `id`, and `aria-controls` must name the same element.

Connect a button to a labelled modal open-modal

<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#confirm-modal">Delete</button>

<div class="modal fade" id="confirm-modal" tabindex="-1" aria-labelledby="confirm-title" aria-hidden="true">
  <div class="modal-dialog"><div class="modal-content">
    <div class="modal-header"><h2 class="modal-title fs-5" id="confirm-title">Confirm deletion</h2></div>
    <div class="modal-body">This cannot be undone.</div>
  </div></div>
</div>

Bootstrap handles focus while the modal is open. Your markup still needs a useful label plus a visible way to close or finish the task.

Activate tooltip elements after rendering enable-tooltips

import Tooltip from 'bootstrap/js/dist/tooltip';

const tooltips = [...document.querySelectorAll('[data-bs-toggle="tooltip"]')]
  .map((element) => new Tooltip(element));

Tooltip attributes do nothing until this constructor runs, and the plugin needs Popper. Keep required instructions visible outside hover-only content.

Show a toast and release its instance show-toast

import Toast from 'bootstrap/js/dist/toast';

const element = document.querySelector('#saved-toast');
const toast = Toast.getOrCreateInstance(element, { delay: 5000 });
toast.show();

element.addEventListener('hidden.bs.toast', () => toast.dispose(), { once: true });

The HTML needs the appropriate live-region semantics. `dispose()` removes Bootstrap's stored instance and event handlers after hiding.

Persist a Bootstrap color mode toggle-color-mode

const root = document.documentElement;

function setTheme(theme) {
  root.setAttribute('data-bs-theme', theme);
  localStorage.setItem('theme', theme);
}

setTheme(localStorage.getItem('theme') || 'light');

`data-bs-theme` swaps Bootstrap's color variables. It does not rewrite custom colors or the styles inside third-party widgets.

Reveal native validation styles on submit validate-form

const form = document.querySelector('.needs-validation');

form.addEventListener('submit', (event) => {
  if (!form.checkValidity()) {
    event.preventDefault();
    event.stopPropagation();
  }
  form.classList.add('was-validated');
});

These classes expose the browser's constraint result. Server-side failures need their own message, invalid state, and accessible field association.

Set Sass variables before the framework consumes them customize-sass

// styles.scss
@import "bootstrap/scss/functions";

$primary: #5b21b6;
$border-radius: .25rem;
$enable-shadows: true;

@import "bootstrap/scss/bootstrap";

Bootstrap 5.3 reads overrides in import order and still uses Sass `@import` internally. Current Dart Sass can emit deprecation warnings for that pipeline.

Clean up an offcanvas before deleting its node dispose-on-removal

import Offcanvas from 'bootstrap/js/dist/offcanvas';

const element = document.querySelector('#filters');
const panel = Offcanvas.getOrCreateInstance(element);

panel.hide();
element.addEventListener('hidden.bs.offcanvas', () => {
  panel.dispose();
  element.remove();
}, { once: true });

A rendering framework can delete the node without notifying Bootstrap. Dispose the instance first so its listeners and stored reference are released.

Alternatives

PackageRegistryPick it when
bulmanpmChoose it when component styling should remain CSS-only and your application will own every interactive state.
tailwindcssnpmChoose it when utilities should support a custom design system instead of prescribing component markup.
@picocss/piconpmChoose it for semantic HTML, few classes, and a smaller set of styled elements and components.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.