# Bootstrap — User Guide

## 1. Quick Start

Bootstrap is the most popular HTML, CSS, and JavaScript front-end framework for building responsive, mobile-first websites and web applications. It provides a comprehensive design system with a 12-column grid, dozens of pre-built components, 12 interactive JavaScript plugins, and a powerful Sass-based customization layer — all in under 30 kB of CSS and 24 kB of JS (gzipped).

### Key Features

- **Responsive grid system** with 6 breakpoints (xs through xxl) and flexbox-based layout
- **12 JavaScript plugins** — Alert, Button, Carousel, Collapse, Dropdown, Modal, Offcanvas, Popover, ScrollSpy, Tab, Toast, Tooltip — all usable via data attributes or JavaScript API
- **Sass-first customization** — override 700+ variables, use mixins and the utilities API to generate only the CSS you need
- **Color modes** — built-in light and dark theme support with automatic OS preference detection
- **RTL support** — right-to-left layouts generated automatically via RTLCSS
- **No jQuery required** — pure vanilla JavaScript; jQuery detected optionally via `window.jQuery` but never mandatory
- **Peer dependency** — only `@popperjs/core` ^2.11.8, and only for Dropdown, Popover, and Tooltip

### CDN Quickstart

Create an `index.html` file with this content to start using Bootstrap immediately:

```html
<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>My Bootstrap Page</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css"
        rel="stylesheet"
        integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB"
        crossorigin="anonymous">
</head>
<body>
  <div class="container py-5">
    <h1>Hello, Bootstrap 5.3.8!</h1>
    <p class="lead">You're up and running.</p>
    <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#demoModal">
      Launch Demo Modal
    </button>

    <div class="modal fade" id="demoModal" tabindex="-1" aria-labelledby="demoModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="demoModalLabel">It Works!</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">Bootstrap is loaded and interactive components are working.</div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          </div>
        </div>
      </div>
    </div>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
          integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
          crossorigin="anonymous"></script>
</body>
</html>
```

Open this file in a browser. You should see a heading, a lead paragraph, and a blue "Launch Demo Modal" button. Clicking the button opens a centered modal dialog — confirming both CSS and JS are loaded correctly.

> [!TIP]
> The **bundle** version (`bootstrap.bundle.min.js`) includes Popper.js, so you get Dropdowns, Popovers, and Tooltips without an extra script tag. Use this unless you have a specific reason to load Popper separately.

**What to try next:** Jump to [Core Usage](#4-core-usage) for the grid system and components, or [Common Tasks](#5-common-tasks) for ready-to-use recipes like responsive navbars and dark mode toggles.

---

## 2. Installation

### Requirements

| Requirement | Minimum | Notes |
|---|---|---|
| Browser | Chrome, Firefox, Edge, Safari (latest 2 major versions) | IE is not supported |
| Node.js | 14+ | Only needed for npm/build workflows |
| Popper.js | `@popperjs/core` ^2.11.8 | Only for Dropdown, Popover, Tooltip — included in the bundle build |
| Sass compiler | Dart Sass 1.33+ | Only if customizing via SCSS |

### Method 1: CDN (No Build Tools)

Add these two tags to your HTML `<head>` and before `</body>`:

```html
<!-- CSS in <head> -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB"
      crossorigin="anonymous">

<!-- JS before </body> -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
        crossorigin="anonymous"></script>
```

For **RTL layouts**, use the RTL CSS instead:

```html
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.rtl.min.css"
      rel="stylesheet"
      integrity="sha384-CfCrinSRH2IR6a4e6fy2q6ioOX7O6Mtm1L9vRvFZ1trBncWmMePhzvafv7oIcWiW"
      crossorigin="anonymous">
```

If you need **separate Popper** (instead of the bundle):

```html
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
        integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
        crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.min.js"
        integrity="sha384-G/EV+4j2dNv+tEPo3++6LCgdCROaejBqfUeNjuKAiuXbjrxilcCdDz6ZAVfHWe1Y"
        crossorigin="anonymous"></script>
```

### Method 2: npm

```bash
npm install bootstrap@5.3.8
```

Expected output:

```
added 2 packages in 3s
```

This installs Bootstrap and its peer dependency `@popperjs/core`. Import in your JavaScript:

```javascript
// ES module import (recommended for bundlers)
import * as bootstrap from 'bootstrap';

// Or import individual plugins
import { Modal, Tooltip } from 'bootstrap';
```

Import the CSS in your bundler entry point or Sass file:

```scss
// Option A: Import all of Bootstrap's CSS
@import "bootstrap/dist/css/bootstrap.min.css";

// Option B: Import Bootstrap's Sass source for customization
@import "bootstrap/scss/bootstrap";
```

The npm package exposes these entry points:

| Field | Path | Use Case |
|---|---|---|
| `main` | `dist/js/bootstrap.js` | CommonJS / UMD |
| `module` | `dist/js/bootstrap.esm.js` | ES modules (tree-shakeable) |
| `sass` | `scss/bootstrap.scss` | Sass source |
| `style` | `dist/css/bootstrap.css` | Pre-compiled CSS |

### Method 3: Composer (PHP)

```bash
composer require twbs/bootstrap:5.3.8
```

### Method 4: NuGet (.NET)

```powershell
Install-Package bootstrap -Version 5.3.8
```

### Method 5: Source Download

| Package | URL |
|---|---|
| Compiled CSS & JS | https://github.com/twbs/bootstrap/releases/download/v5.3.8/bootstrap-5.3.8-dist.zip |
| Source code | https://github.com/twbs/bootstrap/archive/v5.3.8.zip |
| Examples | https://github.com/twbs/bootstrap/releases/download/v5.3.8/bootstrap-5.3.8-examples.zip |

### Verification

After installation, verify Bootstrap is loaded by opening your browser's developer console and running:

```javascript
// Check CSS is loaded — should return a CSSStyleSheet object
document.querySelector('link[href*="bootstrap"]')?.sheet

// Check JS is loaded — should return "5.3.8"
bootstrap.Modal.VERSION
```

> [!IMPORTANT]
> Always include the `integrity` and `crossorigin="anonymous"` attributes when loading from CDN. Subresource Integrity (SRI) protects against compromised CDN files.

---

## 3. Configuration

### Sass Variable Customization

Bootstrap's design is driven by Sass variables. Override them **before** importing Bootstrap:

```scss
// custom.scss

// 1. Override default variables
$primary: #7952b3;
$font-family-base: 'Inter', sans-serif;
$border-radius: 0.5rem;
$enable-shadows: true;
$enable-gradients: true;
$enable-negative-margins: true;

// 2. Import Bootstrap
@import "bootstrap/scss/bootstrap";
```

Compile with Dart Sass:

```bash
sass custom.scss custom.css
```

> [!NOTE]
> You must use Dart Sass (not LibSass or Ruby Sass). If you see deprecation warnings about mixed declarations with Dart Sass 1.80.0+, this is a known upstream issue — the warnings are cosmetic and do not affect output.

### Importing Only What You Need

Reduce your CSS bundle by importing individual components:

```scss
// Required core
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/root";

// Optional components (pick what you use)
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/type";
@import "bootstrap/scss/containers";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/modal";
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/utilities/api"; // Must be last — generates utility classes
```

### Color Modes (Light / Dark / Auto)

Bootstrap 5.3.8 supports color modes via the `data-bs-theme` attribute on `<html>` or any container element:

```html
<!-- Force light mode -->
<html data-bs-theme="light">

<!-- Force dark mode -->
<html data-bs-theme="dark">
```

To **automatically match the OS preference**, add this script before Bootstrap's CSS loads:

```javascript
// Auto-detect and apply color mode
(() => {
  const stored = localStorage.getItem('theme');
  if (stored) {
    document.documentElement.setAttribute('data-bs-theme', stored);
  } else {
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    document.documentElement.setAttribute('data-bs-theme', prefersDark ? 'dark' : 'light');
  }
})();
```

Nest color modes for per-section theming:

```html
<html data-bs-theme="light">
  <body>
    <main>Light content here</main>
    <footer data-bs-theme="dark">
      This footer uses dark mode regardless of the page theme.
    </footer>
  </body>
</html>
```

### Theme Colors

Bootstrap defines 8 semantic theme colors used across components:

| Name | Default Hex | Usage |
|---|---|---|
| `primary` | `#0d6efd` | Buttons, links, active states |
| `secondary` | `#6c757d` | Muted actions, subtle elements |
| `success` | `#28a745` | Positive feedback, confirmations |
| `danger` | `#dc3545` | Errors, destructive actions |
| `warning` | `#ffc107` | Caution states (dark text for contrast) |
| `info` | `#17a2b8` | Informational highlights |
| `light` | `#f8f9fa` | Light backgrounds |
| `dark` | `#343a40` | Dark backgrounds, emphasis |

Override any color via Sass variables before the import (e.g., `$primary: #7952b3;`).

### RTL (Right-to-Left) Support

To enable RTL layout:

1. Set `dir="rtl"` on the `<html>` element
2. Use the RTL CSS build instead of the default:

```html
<html lang="ar" dir="rtl">
<head>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.rtl.min.css"
        rel="stylesheet"
        integrity="sha384-CfCrinSRH2IR6a4e6fy2q6ioOX7O6Mtm1L9vRvFZ1trBncWmMePhzvafv7oIcWiW"
        crossorigin="anonymous">
</head>
```

If building from Sass, set `$enable-rtl: true` and compile with RTLCSS in your pipeline.

### jQuery Compatibility

Bootstrap 5.3.8 does not require jQuery. However, it detects jQuery automatically via `window.jQuery` and will use it if present. To **explicitly disable** jQuery integration even when jQuery is on the page, add a data attribute to the `<body>`:

```html
<body data-bs-no-jquery>
```

For the full Sass variable reference and advanced build configuration, see the **Admin Guide**.

---

## 4. Core Usage

### Layout

#### Containers

Containers are the fundamental layout wrapper. Bootstrap provides three container types:

```html
<!-- Fixed-width container (responsive max-widths at each breakpoint) -->
<div class="container">...</div>

<!-- Full-width container (always 100%) -->
<div class="container-fluid">...</div>

<!-- Responsive container (100% until the specified breakpoint) -->
<div class="container-sm">...</div>
<div class="container-md">...</div>
<div class="container-lg">...</div>
<div class="container-xl">...</div>
<div class="container-xxl">...</div>
```

Container max-widths by breakpoint:

| Breakpoint | Abbr. | Min-Width | `.container` Max-Width |
|---|---|---|---|
| xs | (none) | 0 px | 100% (fluid) |
| sm | `-sm` | 576 px | 540 px |
| md | `-md` | 768 px | 720 px |
| lg | `-lg` | 992 px | 960 px |
| xl | `-xl` | 1200 px | 1140 px |
| xxl | `-xxl` | 1400 px | 1320 px |

#### Grid System

Bootstrap uses a 12-column flexbox grid. Columns must be inside a `.row`, and rows must be inside a container:

```html
<div class="container">
  <div class="row">
    <div class="col-md-8">Main content (8 of 12 columns on md+)</div>
    <div class="col-md-4">Sidebar (4 of 12 columns on md+)</div>
  </div>
</div>
```

**Auto-width columns:**

```html
<div class="row">
  <div class="col">Equal width</div>
  <div class="col">Equal width</div>
  <div class="col">Equal width</div>
</div>
```

**Mixed breakpoints (responsive stacking):**

```html
<div class="row">
  <!-- Full-width on xs/sm, half on md, one-third on lg+ -->
  <div class="col-12 col-md-6 col-lg-4">Card</div>
  <div class="col-12 col-md-6 col-lg-4">Card</div>
  <div class="col-12 col-md-12 col-lg-4">Card</div>
</div>
```

**Row columns (shorthand for equal-width layouts):**

```html
<!-- 1 column on xs, 2 on md, 4 on lg -->
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-4">
  <div class="col">Item</div>
  <div class="col">Item</div>
  <div class="col">Item</div>
  <div class="col">Item</div>
</div>
```

**Gutters:**

```html
<!-- Custom gutter spacing -->
<div class="row g-3">...</div>      <!-- Both horizontal and vertical -->
<div class="row gx-5">...</div>     <!-- Horizontal only -->
<div class="row gy-2">...</div>     <!-- Vertical only -->
<div class="row g-0">...</div>      <!-- No gutters -->
```

**Offsetting columns:**

```html
<div class="row">
  <div class="col-md-6 offset-md-3">Centered 6-column block</div>
</div>
```

### Components (JavaScript Plugins)

All 12 JavaScript plugins can be used in two ways: via **data attributes** (no JavaScript needed) or via the **JavaScript API**. Every plugin fires namespaced events in the pattern `action.bs.component` (e.g., `show.bs.modal`, `hidden.bs.collapse`).

#### Alert

Dismissible alerts with a close button:

```html
<div class="alert alert-warning alert-dismissible fade show" role="alert">
  <strong>Warning!</strong> Check your input before submitting.
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
```

Via JavaScript:

```javascript
const alertEl = document.querySelector('.alert');
const bsAlert = bootstrap.Alert.getOrCreateInstance(alertEl);
bsAlert.close();
```

Events: `close.bs.alert`, `closed.bs.alert`.

#### Button

Toggle active state on buttons:

```html
<button type="button" class="btn btn-primary" data-bs-toggle="button">Toggle Me</button>
```

Via JavaScript:

```javascript
const btn = document.querySelector('.btn');
const bsButton = bootstrap.Button.getOrCreateInstance(btn);
bsButton.toggle();
```

#### Carousel

Image slideshow with controls and indicators:

```html
<div id="myCarousel" class="carousel slide" data-bs-ride="carousel">
  <div class="carousel-indicators">
    <button type="button" data-bs-target="#myCarousel" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
    <button type="button" data-bs-target="#myCarousel" data-bs-slide-to="1" aria-label="Slide 2"></button>
    <button type="button" data-bs-target="#myCarousel" data-bs-slide-to="2" aria-label="Slide 3"></button>
  </div>
  <div class="carousel-inner">
    <div class="carousel-item active">
      <img src="slide1.jpg" class="d-block w-100" alt="First slide">
      <div class="carousel-caption d-none d-md-block">
        <h5>First Slide</h5>
        <p>Description here.</p>
      </div>
    </div>
    <div class="carousel-item">
      <img src="slide2.jpg" class="d-block w-100" alt="Second slide">
    </div>
    <div class="carousel-item">
      <img src="slide3.jpg" class="d-block w-100" alt="Third slide">
    </div>
  </div>
  <button class="carousel-control-prev" type="button" data-bs-target="#myCarousel" data-bs-slide="prev">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Previous</span>
  </button>
  <button class="carousel-control-next" type="button" data-bs-target="#myCarousel" data-bs-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Next</span>
  </button>
</div>
```

Carousel defaults:

| Option | Default | Description |
|---|---|---|
| `interval` | `5000` | Time (ms) between auto-cycling slides |
| `keyboard` | `true` | React to keyboard arrow keys |
| `pause` | `'hover'` | Pause on mouse hover (`false` to disable) |
| `ride` | `false` | Auto-play on load (`'carousel'` to enable) |
| `touch` | `true` | Support swipe on touch devices |
| `wrap` | `true` | Cycle continuously or stop at last slide |

Events: `slide.bs.carousel`, `slid.bs.carousel`.

#### Collapse

Toggle visibility of content:

```html
<a class="btn btn-primary" data-bs-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample">
  Toggle Content
</a>
<div class="collapse" id="collapseExample">
  <div class="card card-body">
    This content is collapsible.
  </div>
</div>
```

Collapse defaults:

| Option | Default | Description |
|---|---|---|
| `parent` | `null` | Selector for accordion behavior (only one open at a time) |
| `toggle` | `true` | Toggle on initialization |

Events: `show.bs.collapse`, `shown.bs.collapse`, `hide.bs.collapse`, `hidden.bs.collapse`.

#### Dropdown

Toggleable menus for navigation and actions:

```html
<div class="dropdown">
  <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
    Dropdown
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#">Action</a></li>
    <li><a class="dropdown-item" href="#">Another action</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">Separated link</a></li>
  </ul>
</div>
```

Dropdown defaults:

| Option | Default | Description |
|---|---|---|
| `autoClose` | `true` | Close behavior: `true`, `'inside'`, `'outside'`, `false` |
| `boundary` | `'clippingParents'` | Overflow constraint boundary for Popper |
| `display` | `'dynamic'` | `'dynamic'` (Popper positioning) or `'static'` |
| `offset` | `[0, 2]` | `[skidding, distance]` in pixels |
| `popperConfig` | `null` | Custom Popper.js configuration object |
| `reference` | `'toggle'` | Reference element: `'toggle'`, `'parent'`, or an HTMLElement |

> [!NOTE]
> Dropdowns require Popper.js. Use the **bundle** build (`bootstrap.bundle.min.js`) or load Popper separately before Bootstrap's JS.

Events: `show.bs.dropdown`, `shown.bs.dropdown`, `hide.bs.dropdown`, `hidden.bs.dropdown`.

#### Modal

Dialogs for confirmations, forms, and content:

```html
<!-- Trigger -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  Open Modal
</button>

<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Modal Title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Modal content goes here.
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-primary">Save</button>
      </div>
    </div>
  </div>
</div>
```

Modal defaults:

| Option | Default | Description |
|---|---|---|
| `backdrop` | `true` | Show backdrop; `'static'` prevents close on backdrop click |
| `focus` | `true` | Focus the modal when opened |
| `keyboard` | `true` | Close on Escape key |

Modal sizes: `.modal-sm`, `.modal-lg`, `.modal-xl`. Fullscreen: `.modal-fullscreen` or responsive variants like `.modal-fullscreen-lg-down`.

Via JavaScript:

```javascript
const modal = new bootstrap.Modal('#exampleModal', {
  backdrop: 'static',
  keyboard: false
});
modal.show();

// Listen for events
document.getElementById('exampleModal').addEventListener('hidden.bs.modal', () => {
  console.log('Modal closed');
});
```

Events: `show.bs.modal`, `shown.bs.modal`, `hide.bs.modal`, `hidden.bs.modal`, `hidePrevented.bs.modal`.

#### Offcanvas

Slide-in side panels (sidebars, mobile navigation):

```html
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
  Open Sidebar
</button>

<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasExample" aria-labelledby="offcanvasExampleLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasExampleLabel">Sidebar</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    Sidebar content here.
  </div>
</div>
```

Offcanvas defaults:

| Option | Default | Description |
|---|---|---|
| `backdrop` | `true` | Show backdrop behind offcanvas |
| `keyboard` | `true` | Close on Escape key |
| `scroll` | `false` | Allow body scrolling while offcanvas is open |

Placement classes: `.offcanvas-start` (left), `.offcanvas-end` (right), `.offcanvas-top`, `.offcanvas-bottom`.

Events: `show.bs.offcanvas`, `shown.bs.offcanvas`, `hide.bs.offcanvas`, `hidden.bs.offcanvas`, `hidePrevented.bs.offcanvas`.

#### Popover

Rich content tooltips (requires Popper.js):

```html
<button type="button" class="btn btn-lg btn-danger"
        data-bs-toggle="popover"
        data-bs-title="Popover Title"
        data-bs-content="This is the popover body content.">
  Click to toggle popover
</button>
```

Initialize all popovers on the page:

```javascript
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]');
const popoverList = [...popoverTriggerList].map(el => new bootstrap.Popover(el));
```

> [!WARNING]
> Popovers are **opt-in** — they are not initialized automatically. You must initialize them via JavaScript as shown above, even when using data attributes for configuration.

Events: `show.bs.popover`, `shown.bs.popover`, `hide.bs.popover`, `hidden.bs.popover`, `inserted.bs.popover`.

#### ScrollSpy

Automatically update navigation based on scroll position:

```html
<nav id="navbar-example" class="navbar navbar-light bg-light px-3">
  <a class="navbar-brand" href="#">Navbar</a>
  <nav class="nav nav-pills">
    <a class="nav-link" href="#section1">Section 1</a>
    <a class="nav-link" href="#section2">Section 2</a>
    <a class="nav-link" href="#section3">Section 3</a>
  </nav>
</nav>

<div data-bs-spy="scroll" data-bs-target="#navbar-example" data-bs-offset="10" tabindex="0"
     style="height: 300px; overflow-y: scroll;">
  <h4 id="section1">Section 1</h4>
  <p>Content...</p>
  <h4 id="section2">Section 2</h4>
  <p>Content...</p>
  <h4 id="section3">Section 3</h4>
  <p>Content...</p>
</div>
```

Events: `activate.bs.scrollspy`.

#### Tab

Tabbed content panels:

```html
<ul class="nav nav-tabs" role="tablist">
  <li class="nav-item" role="presentation">
    <button class="nav-link active" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
  </li>
  <li class="nav-item" role="presentation">
    <button class="nav-link" data-bs-toggle="tab" data-bs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
  </li>
</ul>
<div class="tab-content">
  <div class="tab-pane fade show active" id="home" role="tabpanel">Home content</div>
  <div class="tab-pane fade" id="profile" role="tabpanel">Profile content</div>
</div>
```

Events: `show.bs.tab`, `shown.bs.tab`, `hide.bs.tab`, `hidden.bs.tab`.

#### Toast

Lightweight, dismissible notification messages:

```html
<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <div id="liveToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
    <div class="toast-header">
      <strong class="me-auto">Notification</strong>
      <small>Just now</small>
      <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
    </div>
    <div class="toast-body">
      Your changes have been saved.
    </div>
  </div>
</div>
```

Toasts must be initialized via JavaScript:

```javascript
const toastEl = document.getElementById('liveToast');
const toast = bootstrap.Toast.getOrCreateInstance(toastEl);
toast.show();
```

Events: `show.bs.toast`, `shown.bs.toast`, `hide.bs.toast`, `hidden.bs.toast`.

#### Tooltip

Hover hints (requires Popper.js):

```html
<button type="button" class="btn btn-secondary"
        data-bs-toggle="tooltip" data-bs-placement="top"
        data-bs-title="Tooltip on top">
  Hover me
</button>
```

Initialize all tooltips:

```javascript
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
const tooltipList = [...tooltipTriggerList].map(el => new bootstrap.Tooltip(el));
```

> [!WARNING]
> Like Popovers, Tooltips are **opt-in** and must be initialized via JavaScript. They are not activated by data attributes alone.

Events: `show.bs.tooltip`, `shown.bs.tooltip`, `hide.bs.tooltip`, `hidden.bs.tooltip`, `inserted.bs.tooltip`.

### Forms

Bootstrap provides styled form controls, layout options, and validation:

```html
<form class="needs-validation" novalidate>
  <div class="mb-3">
    <label for="email" class="form-label">Email address</label>
    <input type="email" class="form-control" id="email" required>
    <div class="invalid-feedback">Please enter a valid email.</div>
  </div>
  <div class="mb-3">
    <label for="password" class="form-label">Password</label>
    <input type="password" class="form-control" id="password" required minlength="8">
    <div class="invalid-feedback">Password must be at least 8 characters.</div>
  </div>
  <div class="mb-3 form-check">
    <input type="checkbox" class="form-check-input" id="terms" required>
    <label class="form-check-label" for="terms">Accept terms</label>
    <div class="invalid-feedback">You must agree before submitting.</div>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>
```

Form control classes:

| Element | Class | Notes |
|---|---|---|
| Text inputs | `.form-control` | Also for `textarea`, `email`, `password`, etc. |
| Select | `.form-select` | Replaces default select styling |
| Checkbox / Radio | `.form-check-input` | Wrap in `.form-check` |
| Range | `.form-range` | Custom range slider |
| File input | `.form-control` | Styled file picker |
| Floating labels | `.form-floating` | Wrap around input + label |
| Input group | `.input-group` | Prepend/append text or buttons |

### Typography

```html
<!-- Display headings (larger, bolder) -->
<h1 class="display-1">Display 1</h1>

<!-- Lead paragraph -->
<p class="lead">This is a lead paragraph with larger text.</p>

<!-- Inline text elements -->
<mark>Highlighted</mark>
<del>Deleted</del>
<s>Strikethrough</s>
<small>Fine print</small>

<!-- Blockquote -->
<figure>
  <blockquote class="blockquote">
    <p>A well-known quote.</p>
  </blockquote>
  <figcaption class="blockquote-footer">Someone in <cite title="Source Title">Source Title</cite></figcaption>
</figure>
```

### Utilities

Bootstrap generates dozens of utility classes for rapid styling:

```html
<!-- Spacing: {property}{sides}-{breakpoint}-{size} -->
<div class="mt-3 mb-5 px-4">Margin top 3, margin bottom 5, padding x 4</div>

<!-- Flexbox -->
<div class="d-flex justify-content-between align-items-center">...</div>

<!-- Colors -->
<p class="text-primary bg-light p-3">Primary text on light background</p>

<!-- Borders -->
<div class="border border-primary rounded-3">Bordered element</div>

<!-- Visibility -->
<div class="d-none d-md-block">Hidden on mobile, visible on md+</div>
<div class="d-block d-md-none">Visible on mobile, hidden on md+</div>

<!-- Position -->
<div class="position-fixed top-0 start-0">Fixed top-left</div>

<!-- Shadow -->
<div class="shadow-sm">Small shadow</div>
<div class="shadow">Regular shadow</div>
<div class="shadow-lg">Large shadow</div>
```

---

## 5. Common Tasks

### Responsive Navbar with Mobile Hamburger

```html
<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container">
    <a class="navbar-brand" href="#">MySite</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
            aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav me-auto">
        <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
        <li class="nav-item"><a class="nav-link" href="#">Features</a></li>
        <li class="nav-item"><a class="nav-link" href="#">Pricing</a></li>
      </ul>
      <form class="d-flex" role="search">
        <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
        <button class="btn btn-outline-primary" type="submit">Search</button>
      </form>
    </div>
  </div>
</nav>
```

This navbar is horizontal on `lg` and above, and collapses to a hamburger menu on smaller screens.

### Modal with Form Submission

```html
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#contactModal">
  Contact Us
</button>

<div class="modal fade" id="contactModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Contact Form</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <form id="contactForm">
          <div class="mb-3">
            <label for="contactName" class="form-label">Name</label>
            <input type="text" class="form-control" id="contactName" required>
          </div>
          <div class="mb-3">
            <label for="contactEmail" class="form-label">Email</label>
            <input type="email" class="form-control" id="contactEmail" required>
          </div>
          <div class="mb-3">
            <label for="contactMessage" class="form-label">Message</label>
            <textarea class="form-control" id="contactMessage" rows="3" required></textarea>
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
        <button type="submit" form="contactForm" class="btn btn-primary">Send</button>
      </div>
    </div>
  </div>
</div>
```

### Image Carousel Gallery

```html
<div id="gallery" class="carousel slide" data-bs-ride="carousel" data-bs-interval="3000">
  <div class="carousel-inner rounded-3 shadow">
    <div class="carousel-item active">
      <img src="photo1.jpg" class="d-block w-100" alt="Photo 1">
    </div>
    <div class="carousel-item">
      <img src="photo2.jpg" class="d-block w-100" alt="Photo 2">
    </div>
    <div class="carousel-item">
      <img src="photo3.jpg" class="d-block w-100" alt="Photo 3">
    </div>
  </div>
  <button class="carousel-control-prev" type="button" data-bs-target="#gallery" data-bs-slide="prev">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Previous</span>
  </button>
  <button class="carousel-control-next" type="button" data-bs-target="#gallery" data-bs-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Next</span>
  </button>
</div>
```

### Dark Mode Toggle Button

```html
<button id="themeToggle" class="btn btn-outline-secondary">
  <span id="themeIcon">🌙</span> Toggle Theme
</button>

<script>
  const toggle = document.getElementById('themeToggle');
  const icon = document.getElementById('themeIcon');

  toggle.addEventListener('click', () => {
    const current = document.documentElement.getAttribute('data-bs-theme');
    const next = current === 'dark' ? 'light' : 'dark';
    document.documentElement.setAttribute('data-bs-theme', next);
    localStorage.setItem('theme', next);
    icon.textContent = next === 'dark' ? '☀️' : '🌙';
  });

  // Restore saved preference on load
  const saved = localStorage.getItem('theme') ||
    (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
  document.documentElement.setAttribute('data-bs-theme', saved);
  icon.textContent = saved === 'dark' ? '☀️' : '🌙';
</script>
```

### Custom Theme via Sass

```scss
// mytheme.scss
$primary: #6f42c1;      // Purple
$secondary: #20c997;    // Teal
$font-family-base: 'Poppins', sans-serif;
$border-radius: 1rem;
$enable-shadows: true;

@import "bootstrap/scss/bootstrap";
```

Compile:

```bash
sass mytheme.scss mytheme.css
```

### Client-Side Form Validation

```javascript
// Apply Bootstrap validation styles
(() => {
  'use strict';
  const forms = document.querySelectorAll('.needs-validation');
  Array.from(forms).forEach(form => {
    form.addEventListener('submit', event => {
      if (!form.checkValidity()) {
        event.preventDefault();
        event.stopPropagation();
      }
      form.classList.add('was-validated');
    }, false);
  });
})();
```

Add `novalidate` to the `<form>` and `required`, `minlength`, `pattern`, etc. to inputs. Bootstrap applies `.is-valid` / `.is-invalid` styling when the `.was-validated` class is on the form.

### Toast Notification System

```javascript
function showToast(message, type = 'primary') {
  const container = document.querySelector('.toast-container') || (() => {
    const div = document.createElement('div');
    div.className = 'toast-container position-fixed bottom-0 end-0 p-3';
    document.body.appendChild(div);
    return div;
  })();

  const toastHTML = `
    <div class="toast align-items-center text-bg-${type} border-0" role="alert" aria-live="assertive" aria-atomic="true">
      <div class="d-flex">
        <div class="toast-body">${message}</div>
        <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
      </div>
    </div>`;

  container.insertAdjacentHTML('beforeend', toastHTML);
  const toastEl = container.lastElementChild;
  const toast = new bootstrap.Toast(toastEl, { delay: 5000 });
  toast.show();

  toastEl.addEventListener('hidden.bs.toast', () => toastEl.remove());
}

// Usage
showToast('Settings saved successfully!', 'success');
showToast('Something went wrong.', 'danger');
```

### Sticky Footer Layout

```html
<body class="d-flex flex-column min-vh-100">
  <nav class="navbar navbar-expand-lg bg-body-tertiary">
    <!-- Navbar content -->
  </nav>

  <main class="container flex-grow-1 py-4">
    <!-- Page content -->
  </main>

  <footer class="bg-body-tertiary py-3 mt-auto">
    <div class="container text-center">
      <span class="text-body-secondary">&copy; 2026 My Company</span>
    </div>
  </footer>
</body>
```

The `min-vh-100` on body plus `flex-grow-1` on main ensures the footer stays at the bottom even on short pages.

### Dropdown Navigation Menu

```html
<ul class="nav nav-pills">
  <li class="nav-item">
    <a class="nav-link active" href="#">Home</a>
  </li>
  <li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">
      Products
    </a>
    <ul class="dropdown-menu">
      <li><a class="dropdown-item" href="#">Software</a></li>
      <li><a class="dropdown-item" href="#">Hardware</a></li>
      <li><hr class="dropdown-divider"></li>
      <li><a class="dropdown-item" href="#">All Products</a></li>
    </ul>
  </li>
  <li class="nav-item">
    <a class="nav-link" href="#">About</a>
  </li>
</ul>
```

### Accordion FAQ

```html
<div class="accordion" id="faqAccordion">
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#faq1" aria-expanded="true" aria-controls="faq1">
        What is Bootstrap?
      </button>
    </h2>
    <div id="faq1" class="accordion-collapse collapse show" data-bs-parent="#faqAccordion">
      <div class="accordion-body">
        Bootstrap is a front-end framework for building responsive, mobile-first websites.
      </div>
    </div>
  </div>
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faq2" aria-expanded="false" aria-controls="faq2">
        Is Bootstrap free?
      </button>
    </h2>
    <div id="faq2" class="accordion-collapse collapse" data-bs-parent="#faqAccordion">
      <div class="accordion-body">
        Yes. Bootstrap is released under the MIT License and is free for personal and commercial use.
      </div>
    </div>
  </div>
</div>
```

The `data-bs-parent="#faqAccordion"` ensures only one item is open at a time (accordion behavior via the Collapse plugin with a `parent` option).

### Responsive Card Grid

```html
<div class="container">
  <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
    <div class="col">
      <div class="card h-100">
        <img src="card1.jpg" class="card-img-top" alt="Card 1">
        <div class="card-body">
          <h5 class="card-title">Card Title</h5>
          <p class="card-text">Card description goes here.</p>
        </div>
        <div class="card-footer">
          <a href="#" class="btn btn-primary">Read More</a>
        </div>
      </div>
    </div>
    <!-- Repeat for more cards -->
  </div>
</div>
```

The `h-100` class ensures all cards in a row are equal height. `row-cols-*` sets the number of columns per row at each breakpoint.

### Offcanvas Mobile Sidebar

```html
<button class="btn btn-primary d-lg-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebar">
  Menu
</button>

<div class="offcanvas-lg offcanvas-start" tabindex="-1" id="sidebar">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title">Menu</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <nav class="nav flex-column">
      <a class="nav-link active" href="#">Dashboard</a>
      <a class="nav-link" href="#">Orders</a>
      <a class="nav-link" href="#">Products</a>
      <a class="nav-link" href="#">Customers</a>
    </nav>
  </div>
</div>
```

The `.offcanvas-lg` class makes this a slide-in panel on screens smaller than `lg`, and a static visible sidebar on `lg` and above.

---

## 6. Troubleshooting

### Diagnostic Decision Tree

```
Component not working?
├── CSS loaded?
│   ├── No  → Add Bootstrap CSS <link> to <head>
│   └── Yes → JS loaded?
│       ├── No  → Add Bootstrap JS before </body>
│       └── Yes → Using Popper-dependent component? (Dropdown/Popover/Tooltip)
│           ├── Yes → Using bundle.min.js or separate Popper?
│           │   ├── Neither → Add bundle.min.js or load Popper first
│           │   └── Both loaded → Check initialization (Popovers/Tooltips are opt-in)
│           └── No  → Check data attributes (must use data-bs-* prefix, not data-*)
│               └── Still broken? → Check console for JS errors
│                   └── Multiple Bootstrap versions loaded? Remove duplicates.
```

### Error: `Uncaught TypeError: bootstrap.Modal is not a constructor`

**Cause:** Bootstrap JS is not loaded, or you are loading the ESM build in a non-module script tag.

**Solution:** Ensure the script tag is present and uses the UMD build:

```html
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
        crossorigin="anonymous"></script>
```

If using the ESM build, the script tag must have `type="module"`:

```html
<script type="module">
  import { Modal } from 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.esm.min.js';
</script>
```

**Prevention:** Use the bundle UMD build for simple projects; reserve ESM for bundler-based setups.

### Error: `Popper is required for dropdowns/tooltips/popovers`

**Cause:** You loaded `bootstrap.min.js` (which does not include Popper) without loading Popper separately.

**Solution:** Either switch to the bundle build or add Popper before Bootstrap:

```html
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
        integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
        crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.min.js"
        integrity="sha384-G/EV+4j2dNv+tEPo3++6LCgdCROaejBqfUeNjuKAiuXbjrxilcCdDz6ZAVfHWe1Y"
        crossorigin="anonymous"></script>
```

**Prevention:** Default to `bootstrap.bundle.min.js` unless you have a specific reason to exclude Popper.

### Tooltips and Popovers Not Appearing

**Cause:** These plugins are opt-in and not automatically initialized from data attributes alone.

**Solution:** Initialize them explicitly via JavaScript:

```javascript
// Initialize all tooltips
document.querySelectorAll('[data-bs-toggle="tooltip"]')
  .forEach(el => new bootstrap.Tooltip(el));

// Initialize all popovers
document.querySelectorAll('[data-bs-toggle="popover"]')
  .forEach(el => new bootstrap.Popover(el));
```

**Prevention:** Add initialization code in a `DOMContentLoaded` listener or at the end of `<body>`.

### Error: `TypeError` When Popover `data-bs-content` Is `"true"` or `"false"`

**Cause:** When `data-bs-content` is set to the string `"true"` or `"false"`, Bootstrap's attribute parsing auto-converts it to a boolean, causing a `TypeError` when the Popover plugin tries to use it as string content. This is a known issue (GitHub #41925).

**Solution:** Wrap the value in extra characters to prevent boolean coercion:

```html
<!-- Instead of data-bs-content="true" -->
<button data-bs-toggle="popover" data-bs-content="Value: true">Info</button>
```

Or set content via JavaScript:

```javascript
new bootstrap.Popover(el, { content: 'true' });
```

**Prevention:** Avoid using bare `"true"` or `"false"` as popover content strings.

### Dropdowns Not Appearing in Dark Mode / Dark Navbar

**Cause:** Dark dropdowns and navbars may not automatically inherit dark-mode CSS custom properties when the `data-bs-theme="dark"` attribute is set at the page level. This is a known styling gap (GitHub #39984).

**Solution:** Explicitly add the `data-bs-theme="dark"` attribute directly on the dropdown menu or navbar element:

```html
<div class="dropdown-menu" data-bs-theme="dark">
  <!-- items -->
</div>
```

**Prevention:** When using dark mode, test dropdown and navbar components explicitly and apply `data-bs-theme` at the component level if the page-level attribute is not inherited.

### Dart Sass 1.80.0+ Deprecation Warnings

**Cause:** Dart Sass 1.80.0 and newer emit deprecation warnings for mixed declarations — a pattern used in Bootstrap's Sass source. This is cosmetic and does not affect the compiled CSS output (GitHub #40962).

**Solution:** Suppress the warnings in your build tool:

```bash
sass --quiet-deps custom.scss custom.css
```

Or in a bundler configuration (e.g., webpack):

```javascript
// webpack.config.js
{
  loader: 'sass-loader',
  options: {
    sassOptions: {
      quietDeps: true
    }
  }
}
```

**Prevention:** Pin Dart Sass below 1.80.0 if warnings are disruptive, or use `--quiet-deps` in your build scripts.

### Missing `aria-pressed="false"` on Toggle Buttons

**Cause:** Toggle buttons initialized via `data-bs-toggle="button"` do not automatically set `aria-pressed="false"` at initialization — only `aria-pressed="true"` is set when toggled on (GitHub #42328).

**Solution:** Manually add the attribute in your HTML:

```html
<button type="button" class="btn btn-primary" data-bs-toggle="button" aria-pressed="false">
  Toggle
</button>
```

**Prevention:** Always include `aria-pressed="false"` on toggle buttons for screen reader compatibility.

### Modal Backdrop Remains After Close

**Cause:** Programmatically calling `modal.hide()` before the show transition finishes, or removing the modal element from the DOM while it is still visible.

**Solution:** Listen for the `shown.bs.modal` event before calling hide, and use `dispose()` before removing from DOM:

```javascript
const modal = bootstrap.Modal.getInstance(element);
modal.hide();
element.addEventListener('hidden.bs.modal', () => {
  modal.dispose();
  element.remove();
});
```

**Prevention:** Always wait for transition events to complete before programmatically manipulating modals.

### Grid Columns Not Stacking on Mobile

**Cause:** Using only `col-lg-6` without a mobile fallback means columns are auto-sized (not full-width) on smaller screens.

**Solution:** Add `col-12` as the base and layer on responsive overrides:

```html
<div class="row">
  <div class="col-12 col-lg-6">Full on mobile, half on desktop</div>
  <div class="col-12 col-lg-6">Full on mobile, half on desktop</div>
</div>
```

**Prevention:** Always start with the smallest breakpoint and add responsive classes upward (mobile-first).

### JavaScript Plugin Instances Leaking Memory

**Cause:** Calling `new bootstrap.Modal(el)` multiple times on the same element creates duplicate instances.

**Solution:** Use `getOrCreateInstance()` instead of the constructor:

```javascript
// Correct: reuses existing instance
const modal = bootstrap.Modal.getOrCreateInstance(el);

// Also correct: check first
const existing = bootstrap.Modal.getInstance(el);
if (!existing) {
  new bootstrap.Modal(el);
}
```

**Prevention:** Use `getOrCreateInstance()` as your default pattern for all plugin initialization.

### Data Attributes Using Wrong Prefix

**Cause:** Using `data-toggle` or `data-dismiss` (Bootstrap 4 syntax) instead of the `data-bs-*` prefix required by Bootstrap 5.

**Solution:** Add the `bs-` infix to all data attributes:

```html
<!-- Wrong (Bootstrap 4) -->
<button data-toggle="modal" data-target="#myModal">Open</button>

<!-- Correct (Bootstrap 5) -->
<button data-bs-toggle="modal" data-bs-target="#myModal">Open</button>
```

**Prevention:** Search your codebase for `data-toggle` and `data-dismiss` and replace with `data-bs-toggle` and `data-bs-dismiss`.

---

## 7. FAQ

### General

**Does Bootstrap require jQuery?**
No. Bootstrap 5.3.8 is written in vanilla JavaScript. If jQuery is present on the page, Bootstrap detects it via `window.jQuery` and uses it automatically. You can disable this by adding `data-bs-no-jquery` to the `<body>` tag.

**What license is Bootstrap released under?**
MIT License. It is free for personal and commercial use with no restrictions.

**What is the current version?**
5.3.8. You can verify at runtime with `bootstrap.Modal.VERSION` (or any plugin's `.VERSION` property), which returns `"5.3.8"`.

**How large is Bootstrap?**
The core CSS is under 30.25 kB gzipped (`bootstrap.min.css`), the JS bundle (including Popper) is under 23.5 kB gzipped (`bootstrap.bundle.min.js`), and the standalone JS is under 16.25 kB gzipped (`bootstrap.min.js`).

### Installation & Setup

**Can I use Bootstrap without npm or a build tool?**
Yes. The CDN method requires zero build tools — just two HTML tags (one `<link>` for CSS, one `<script>` for JS). See [Quick Start](#1-quick-start).

**How do I include only the components I need?**
Import individual Sass files instead of the full `bootstrap.scss`. For JavaScript, use ES module imports to pull in only the plugins you need (bundlers will tree-shake unused code):

```javascript
import { Modal, Tooltip } from 'bootstrap';
```

**Do I need Popper.js?**
Only if you use Dropdown, Popover, or Tooltip. The `bootstrap.bundle.min.js` build includes Popper. If you don't use those three components, use `bootstrap.min.js` instead and skip Popper entirely.

### Customization

**How do I change the primary color?**
Set `$primary` before importing Bootstrap in your Sass file:

```scss
$primary: #7952b3;
@import "bootstrap/scss/bootstrap";
```

**How do I enable dark mode?**
Add `data-bs-theme="dark"` to the `<html>` element. For automatic OS-preference detection, see the [dark mode toggle recipe](#dark-mode-toggle-button) in Common Tasks.

**Can I use Bootstrap with Tailwind CSS?**
Technically possible but not recommended. Both frameworks generate utility classes that will conflict (e.g., `.container`, `.flex`, `.hidden`). Choose one framework per project.

### Components

**Why aren't my Tooltips/Popovers working?**
They require explicit JavaScript initialization. Add this after Bootstrap JS loads:

```javascript
document.querySelectorAll('[data-bs-toggle="tooltip"]')
  .forEach(el => new bootstrap.Tooltip(el));
```

**How do I prevent the modal from closing when clicking outside?**
Set `backdrop` to `'static'`:

```html
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
```

**What is the difference between `bootstrap.min.js` and `bootstrap.bundle.min.js`?**
The bundle includes Popper.js (~7 kB). Use the bundle unless you load Popper separately or don't need Dropdown, Popover, or Tooltip components.

**How do I listen for component events?**
All plugins fire namespaced DOM events. Listen with standard `addEventListener`:

```javascript
document.getElementById('myModal').addEventListener('shown.bs.modal', (event) => {
  console.log('Modal is now visible');
});
```

### Migration & Compatibility

> [!CAUTION]
> If migrating from Bootstrap 4, the most common breaking change is the data attribute prefix. All `data-*` attributes are now `data-bs-*`. A global find-and-replace of `data-toggle` to `data-bs-toggle` and `data-dismiss` to `data-bs-dismiss` addresses most issues.

**Does Bootstrap support IE 11?**
No. Bootstrap 5 dropped Internet Explorer support entirely. The last version supporting IE 11 is Bootstrap 4.6.x.

**Can I use Bootstrap with React/Vue/Angular?**
Yes, but consider using framework-specific wrappers like `react-bootstrap` or `ng-bootstrap` that replace Bootstrap's JS with native framework components. If using Bootstrap's JS directly, initialize plugins in lifecycle hooks (e.g., `useEffect` in React, `onMounted` in Vue) and call `dispose()` on cleanup.

---

_Generated May 2026 from twbs/bootstrap at 5d302a0. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
