DEV SCRIPTS

Bootstrap Code FAQs

Bootstrap FAQ

Bootstrap FAQ

Practical questions & answers from the grid system to advanced customization

100 Questions • 12 Categories
What is Bootstrap

The CDN approach links to pre-built CSS and JS files hosted on a content delivery network — zero build step, instant start. The npm approach installs Bootstrap’s Sass source and JS modules so you can tree-shake unused components, override variables, and build a custom bundle. CDN is for quick prototypes; npm is for production apps.

html
<!-- CDN — paste into <head> and before </body> -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

<!-- npm — install then import in your entry file -->
<!-- npm install bootstrap -->

<!-- main.scss -->
// @import "bootstrap/scss/bootstrap";  // full
// @import "bootstrap/scss/functions";  // custom — only what you need
// @import "bootstrap/scss/variables";
// @import "bootstrap/scss/grid";

<!-- main.js -->
// import 'bootstrap';          // full JS bundle
// import { Modal } from 'bootstrap'; // tree-shaken — only Modal

Bootstrap 5 dropped jQuery entirely — the JavaScript is pure vanilla ES6. It added a utility API for generating custom utility classes, switched from float-based layout to Flexbox/Grid, added RTL support, and expanded the utility classes (gap, position, overflow). Breakpoints gained an xxl tier.

html
<!-- Bootstrap 4 required jQuery -->
<script src="jquery.min.js"></script>
<script src="bootstrap.min.js"></script>

<!-- Bootstrap 5 — jQuery free -->
<script src="bootstrap.bundle.min.js"></script>

<!-- New in BS5 -->
<!-- gap utilities: gap-3, gap-x-2, gap-y-4 -->
<!-- position utilities: top-50, start-50, translate-middle -->
<!-- xxl breakpoint: col-xxl-4 -->
<!-- Floating labels, offcanvas, accordion component -->
<!-- RTL support via dir="rtl" + bootstrap.rtl.css -->

Mobile-first means unbreakpointed classes apply to all screen sizes, and breakpointed classes override upward. Write your mobile layout first, then add breakpoint suffixes to change behavior at larger screens. This produces smaller CSS because the base styles cover the most common (small) case.

html
<!-- Mobile-first reading:
  col-12    → all sizes (mobile base)
  col-md-6  → md (768px) and up: half width
  col-lg-4  → lg (992px) and up: one third -->
<div class="col-12 col-md-6 col-lg-4">Card</div>

<!-- text-center applies everywhere;
     text-md-start overrides at ≥768px -->
<p class="text-center text-md-start">Responsive text alignment</p>

<!-- d-none hides on mobile;
     d-md-block shows at ≥768px -->
<div class="d-none d-md-block">Desktop only</div>

<!-- Breakpoints: xs(default) sm(576) md(768) lg(992) xl(1200) xxl(1400) -->

The bundle version includes Popper.js (for tooltips, dropdowns, and popovers) already concatenated. The standalone version excludes Popper — you’d need to include it separately. Almost always use the bundle; use standalone only if you’re loading Popper separately for version control.

html
<!-- Option 1: bundle (recommended — Popper included) -->
<script src="bootstrap.bundle.min.js"></script>

<!-- Option 2: separate (Popper must load first) -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"></script>
<script src="bootstrap.min.js"></script>

<!-- Components that NEED Popper:
  Dropdowns, Tooltips, Popovers

  Components that do NOT need Popper:
  Modals, Alerts, Collapses, Carousels, Toasts -->

Bootstrap provides ready-made components (cards, navbars, modals) and a comprehensive set of single-purpose utility classes for spacing, color, flexbox, and typography. You compose utilities to customize components without writing custom CSS — keeping styling in HTML and making changes predictable.

html
<!-- Component + utilities — no custom CSS needed -->
<div class="card shadow-sm border-0 rounded-4 mb-4">
  <div class="card-body p-4">
    <h5 class="card-title fw-bold text-primary mb-2">Order #1042</h5>
    <p class="card-text text-muted small mb-3">Placed on June 10, 2026</p>
    <div class="d-flex gap-2">
      <span class="badge bg-success-subtle text-success">Shipped</span>
      <span class="badge bg-secondary-subtle text-secondary">3 items</span>
    </div>
  </div>
</div>

Bootstrap 5.3 exposes its design tokens as CSS custom properties (variables) on :root. Override them in your own stylesheet to change colors, font sizes, and border radii globally — no build step required. Component styles reference these variables, so overriding one variable updates all components that use it.

css
/* Override Bootstrap CSS variables after importing Bootstrap */
:root {
  --bs-primary:        #7B2FBE;
  --bs-primary-rgb:    123, 47, 190;
  --bs-border-radius:  0.5rem;
  --bs-font-sans-serif: 'Inter', system-ui, sans-serif;
  --bs-body-font-size: 0.95rem;
  --bs-link-color:     #7B2FBE;
}

/* Component-level override */
.btn-primary {
  --bs-btn-bg:           #7B2FBE;
  --bs-btn-hover-bg:     #5B1A9A;
  --bs-btn-border-color: #7B2FBE;
}

Bootstrap 5.3 introduced a built-in color mode system. Set data-bs-theme="dark" on any element (or <html> for the whole page) to switch to dark mode. Bootstrap ships a full dark palette via CSS custom properties — no extra stylesheet needed. Toggle programmatically or follow prefers-color-scheme.

html
<!-- Whole page dark -->
<html data-bs-theme="dark">

<!-- Scoped dark — just this card -->
<div class="card" data-bs-theme="dark">
  <div class="card-body">Dark card on a light page</div>
</div>

<!-- JS toggle -->
<script>
const toggle = () => {
  const html = document.documentElement;
  html.setAttribute('data-bs-theme',
    html.getAttribute('data-bs-theme') === 'dark' ? 'light' : 'dark'
  );
};
</script>

<!-- Follow OS preference -->
<script>
const preferred = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
document.documentElement.setAttribute('data-bs-theme', preferred);
</script>

Bootstrap Icons is a separate library of 2,000+ SVG icons. Include via CDN or npm. Use the <i class="bi bi-{name}"> syntax (font-based) or embed inline SVG for the best performance. Size with font-size utilities; color with text utilities.

html
<!-- CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">

<!-- Font icon usage -->
<i class="bi bi-house-door"></i>
<i class="bi bi-heart-fill text-danger fs-4"></i>
<i class="bi bi-search text-muted"></i>

<!-- In a button -->
<button class="btn btn-primary">
  <i class="bi bi-plus-lg me-1"></i> Add Item
</button>

<!-- Inline SVG (better accessibility) -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-check-circle text-success">
  <use href="bootstrap-icons.svg#check-circle"/>
</svg>
Grid System

Every Bootstrap grid starts with a .container (or .container-fluid) that centers and constrains content. Inside, .row creates a flex row and applies negative horizontal margins to compensate for column padding. .col-* children divide the 12-column space. Never put content directly in a row — always use columns.

html
<div class="container">         <!-- max-width + centering -->
  <div class="row">             <!-- flex row + gutter magic -->
    <div class="col-12 col-md-8">Main content</div>
    <div class="col-12 col-md-4">Sidebar</div>
  </div>
</div>

<!-- Container variants -->
<div class="container"></div>           <!-- responsive max-widths -->
<div class="container-fluid"></div>     <!-- always 100% width -->
<div class="container-md"></div>        <!-- fluid until md, then fixed -->
<div class="container-xxl"></div>       <!-- fluid until xxl (1400px) -->

Using .col without a number makes each column take an equal share of the row. Mix sized and auto columns — sized ones take their declared width, and auto-columns share the remainder equally. .col-auto shrinks to fit its content.

html
<!-- Three equal columns -->
<div class="row">
  <div class="col">One</div>
  <div class="col">Two</div>
  <div class="col">Three</div>
</div>

<!-- Mix: fixed + auto -->
<div class="row">
  <div class="col-4">Fixed 4</div>  <!-- takes 4/12 -->
  <div class="col">Auto fills rest</div>
  <div class="col">Auto fills rest</div>
</div>

<!-- col-auto — width of content -->
<div class="row align-items-center">
  <div class="col-auto"><img src="avatar.png" width="40"></div>
  <div class="col">Username fills remaining space</div>
</div>

Offset classes add left margin equivalent to a number of columns. offset-md-3 pushes a column 3 column-widths to the right at the medium breakpoint and above. Reset offsets with offset-lg-0 at larger breakpoints.

html
<!-- Centered narrow column -->
<div class="row">
  <div class="col-6 offset-3">Centered 6-column content</div>
</div>

<!-- Responsive offset -->
<div class="row">
  <div class="col-sm-5 col-md-6">First</div>
  <div class="col-sm-5 offset-sm-2 col-md-6 offset-md-0">Second</div>
  <!-- at sm: 5+2 gap+5 = 12; at md: 6+6=12, offset removed -->
</div>

<!-- margin utilities as alternative -->
<div class="row">
  <div class="col-4 ms-auto">Pushed to the right</div>
</div>

Gutters are the horizontal and vertical padding between columns. Set with g-* (both axes), gx-* (horizontal), or gy-* (vertical) on the row. Values 0–5 map to the spacing scale. g-0 removes gutters entirely for edge-to-edge layouts.

html
<!-- Standard gutters -->
<div class="row g-3">
  <div class="col-6"><div class="p-3 bg-light">A</div></div>
  <div class="col-6"><div class="p-3 bg-light">B</div></div>
</div>

<!-- No horizontal gap, vertical gap only -->
<div class="row gx-0 gy-4">
  <div class="col-6">No horizontal gap</div>
  <div class="col-6">But vertical spacing</div>
</div>

<!-- Edge-to-edge image grid -->
<div class="row g-0">
  <div class="col-4"><img src="a.jpg" class="img-fluid"></div>
  <div class="col-4"><img src="b.jpg" class="img-fluid"></div>
  <div class="col-4"><img src="c.jpg" class="img-fluid"></div>
</div>

order-* sets the CSS flex order. Columns with lower order values appear first visually. Responsive variants like order-md-1 let you reorder content between mobile (sidebar below content) and desktop (sidebar before content) without duplicating HTML.

html
<!-- Mobile: content first, sidebar second
     Desktop: sidebar first, content second -->
<div class="row">
  <div class="col-12 col-md-8 order-md-2">Main content</div>
  <div class="col-12 col-md-4 order-md-1">Sidebar</div>
</div>

<!-- Named orders: first (-1), last (6) -->
<div class="row">
  <div class="col order-3">Third</div>
  <div class="col order-1">First</div>
  <div class="col order-2">Second</div>
</div>

<!-- order-first and order-last helpers -->
<div class="col order-last">Rendered first in HTML, shown last</div>

Place a new .row directly inside any .col-* to subdivide that column into 12 sub-columns. The inner grid is self-contained — inner columns add up to 12 within the parent column, not the page.

html
<div class="container">
  <div class="row">
    <div class="col-md-8">
      <!-- Nested row subdivides the col-md-8 into 12 -->
      <div class="row">
        <div class="col-6">Left half of main</div>
        <div class="col-6">Right half of main</div>
      </div>
      <div class="row mt-3">
        <div class="col-4">Third</div>
        <div class="col-4">Third</div>
        <div class="col-4">Third</div>
      </div>
    </div>
    <div class="col-md-4">Sidebar</div>
  </div>
</div>

row-cols-* on a row sets how many columns fit per row. Combined with .col children, it creates an automatic equal-width card grid without specifying breakpoints on each card. Responsive variants change the count at different screen sizes.

html
<!-- 1 col on mobile, 2 on sm, 3 on md, 4 on lg -->
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 g-3">
  <div class="col">
    <div class="card h-100">
      <div class="card-body">Product 1</div>
    </div>
  </div>
  <div class="col">
    <div class="card h-100">
      <div class="card-body">Product 2</div>
    </div>
  </div>
  <!-- Add as many .col children as needed — wraps automatically -->
</div>

Bootstrap 5.1+ includes an opt-in CSS Grid mode. Add .grid instead of .row and use g-col-* classes. It uses native CSS grid instead of flexbox, enabling true 2D placement, gap without negative margins, and grid-column spanning.

html
<!-- Enable CSS Grid mode (opt-in via .grid class) -->
<div class="grid">
  <div class="g-col-6">Half</div>
  <div class="g-col-6">Half</div>
  <div class="g-col-4">Third</div>
  <div class="g-col-4">Third</div>
  <div class="g-col-4">Third</div>
</div>

<!-- Responsive CSS Grid -->
<div class="grid">
  <div class="g-col-12 g-col-md-6">Responsive</div>
  <div class="g-col-12 g-col-md-6">Responsive</div>
</div>

<!-- span across columns (native grid feature) -->
<div class="grid">
  <div class="g-col-12">Full width header</div>
  <div class="g-col-8">Main</div>
  <div class="g-col-4">Aside</div>
</div>
Typography & Colors

Bootstrap’s .display-* classes (1–6) produce extra-large hero headings — larger and lighter than h1h6. .lead makes a paragraph slightly larger and lighter-weight for introductory text. Use heading classes (.h1.h6) to apply heading styles to non-heading elements.

html
<h1 class="display-1">Display 1</h1>  <!-- largest -->
<h2 class="display-4">Display 4</h2>  <!-- hero section size -->
<h6 class="display-6">Display 6</h6>  <!-- smallest display -->

<p class="lead">Slightly larger introductory paragraph text.</p>

<!-- Heading classes on non-heading elements -->
<p class="h3">Looks like h3, but is a paragraph</p>
<span class="h5">Looks like h5</span>

<!-- Font weight and style utilities -->
<p class="fw-bold">Bold</p>
<p class="fw-semibold">Semibold</p>
<p class="fw-normal">Normal</p>
<p class="fst-italic">Italic</p>

Bootstrap provides text-{color} and bg-{color} utilities for each theme color (primary, secondary, success, danger, warning, info, light, dark, body, muted, white, black). Bootstrap 5.3 added text-emphasis and bg-subtle variants for softer tones.

html
<!-- Text colors -->
<p class="text-primary">Primary</p>
<p class="text-success">Success</p>
<p class="text-danger">Danger</p>
<p class="text-muted">Muted (secondary text)</p>
<p class="text-body-secondary">Body secondary (BS 5.3)</p>

<!-- Background colors -->
<div class="bg-primary text-white p-3">Primary background</div>
<div class="bg-success-subtle text-success-emphasis p-3">Soft success (BS 5.3)</div>
<div class="bg-danger-subtle text-danger-emphasis p-3">Soft danger</div>

<!-- Opacity modifier -->
<div class="text-primary text-opacity-50">50% opacity primary</div>
<div class="bg-dark bg-opacity-25 p-3">25% dark background</div>

Bootstrap provides responsive text alignment (text-start, text-center, text-end), text transform (text-uppercase, text-lowercase, text-capitalize), and decoration utilities (text-decoration-none, text-decoration-underline). All support responsive breakpoint variants.

html
<!-- Alignment -->
<p class="text-center">Centered</p>
<p class="text-end">Right-aligned</p>
<p class="text-md-center">Centered at md+</p>

<!-- Transform -->
<p class="text-uppercase">uppercase</p>
<p class="text-capitalize">first letter capitalized</p>
<p class="text-lowercase">FORCED TO LOWERCASE</p>

<!-- Decoration -->
<a href="#" class="text-decoration-none">No underline</a>
<span class="text-decoration-underline">Underlined span</span>
<span class="text-decoration-line-through">Strikethrough</span>

<!-- Truncation -->
<p class="text-truncate" style="max-width:200px">Long text that gets truncated with ellipsis</p>

fs-* classes (1–6) set font sizes using the same scale as headings. They use rem units that scale with the root font size. Combine with responsive variants for text that changes size at different breakpoints.

html
<!-- Font size scale -->
<p class="fs-1">fs-1 — 2.5rem (h1 size)</p>
<p class="fs-2">fs-2 — 2rem</p>
<p class="fs-3">fs-3 — 1.75rem</p>
<p class="fs-4">fs-4 — 1.5rem</p>
<p class="fs-5">fs-5 — 1.25rem</p>
<p class="fs-6">fs-6 — 1rem (body default)</p>

<!-- Small text -->
<small class="text-muted">Small text</small>
<span class="small">Also small</span>

<!-- Line height -->
<p class="lh-1">Line height 1 (tight)</p>
<p class="lh-sm">Small line height</p>
<p class="lh-base">Base line height</p>
<p class="lh-lg">Large line height (loose)</p>

Bootstrap styles blockquotes via the .blockquote class with an optional .blockquote-footer for attribution. Inline code gets a colored background automatically with <code>; block code uses <pre><code>. .kbd styles keyboard shortcuts.

html
<!-- Blockquote -->
<figure>
  <blockquote class="blockquote">
    <p>A well-known quote, contained in a blockquote element.</p>
  </blockquote>
  <figcaption class="blockquote-footer">
    Someone famous in <cite title="Source Title">Source Title</cite>
  </figcaption>
</figure>

<!-- Inline code -->
<p>Use <code>const x = 1;</code> to declare a variable.</p>

<!-- Code block -->
<pre><code>const greet = name => `Hello, ${name}!`;</code></pre>

<!-- Keyboard shortcut -->
<p>Press <kbd>Ctrl</kbd> + <kbd>S</kbd> to save.</p>

.list-unstyled removes bullets and left padding from a <ul> or <ol>. .list-inline with .list-inline-item displays list items horizontally. The .list-group component adds borders and structure to create navigation or content lists.

html
<!-- Remove bullets -->
<ul class="list-unstyled">
  <li>No bullet</li>
  <li>No bullet</li>
</ul>

<!-- Horizontal list -->
<ul class="list-inline">
  <li class="list-inline-item">One</li>
  <li class="list-inline-item">·</li>
  <li class="list-inline-item">Two</li>
  <li class="list-inline-item">·</li>
  <li class="list-inline-item">Three</li>
</ul>

<!-- Description list alignment -->
<dl class="row">
  <dt class="col-sm-3">Description lists</dt>
  <dd class="col-sm-9">A description list is perfect for defining terms.</dd>
</dl>

Adding .bg-gradient alongside a bg-* color class overlays a CSS gradient on the background. Bootstrap uses a subtle linear gradient that goes from a semi-transparent white at the top to transparent at the bottom — adding a lift effect. Combine with opacity utilities for adjustment.

html
<!-- Gradient on theme colors -->
<div class="bg-primary bg-gradient text-white p-4 rounded">
  Gradient primary background
</div>

<div class="bg-dark bg-gradient text-white p-4 rounded mt-3">
  Gradient dark background
</div>

<!-- Hero section with gradient -->
<section class="bg-primary bg-gradient py-5">
  <div class="container text-white">
    <h1 class="display-4 fw-bold">Hero Heading</h1>
    <p class="lead">Subtitle text goes here.</p>
    <a href="#" class="btn btn-light btn-lg">Get Started</a>
  </div>
</section>

Bootstrap’s border utilities add or remove borders (border, border-top, border-0), set border color (border-primary), width (border-2), and radius (rounded, rounded-circle, rounded-pill, rounded-4).

html
<!-- Add/remove borders -->
<div class="border p-3">All borders</div>
<div class="border-top border-bottom p-3">Top and bottom only</div>
<div class="border border-0 border-md p-3">Border at md+</div>

<!-- Border color and width -->
<div class="border border-primary border-2 p-3">Primary 2px border</div>
<div class="border border-danger border-3 p-3">Danger 3px border</div>

<!-- Border radius -->
<img src="avatar.jpg" class="rounded-circle" width="80">  <!-- circle -->
<div class="rounded-pill px-4 py-2 bg-primary text-white">Pill shape</div>
<div class="rounded-4 p-3 bg-light">Large radius</div>  <!-- BS 5.2+ -->
Components — UI Elements

Bootstrap provides filled (btn-primary), outlined (btn-outline-primary), and link buttons. Sizes use btn-lg/btn-sm. States include active (.active), disabled (disabled attr), and loading (add spinner manually). Buttons can be links or inputs styled as buttons.

html
<!-- Variants -->
<button class="btn btn-primary">Primary</button>
<button class="btn btn-outline-secondary">Outline</button>
<button class="btn btn-success">Success</button>
<button class="btn btn-danger">Danger</button>
<button class="btn btn-link">Link style</button>

<!-- Sizes -->
<button class="btn btn-primary btn-lg">Large</button>
<button class="btn btn-primary btn-sm">Small</button>

<!-- States -->
<button class="btn btn-primary active">Active</button>
<button class="btn btn-primary" disabled>Disabled</button>

<!-- Loading state (manual) -->
<button class="btn btn-primary" id="saveBtn">
  <span class="spinner-border spinner-border-sm d-none me-1" id="spinner"></span>
  Save
</button>

<!-- Full-width button -->
<button class="btn btn-primary w-100">Full width</button>

Cards are flexible content containers with optional header, body, footer, and image. card-img-top places an image at the top; card-img-overlay layers content on top of an image. Use h-100 on cards inside equal-height grid rows.

html
<!-- Standard card -->
<div class="card" style="width:18rem">
  <img src="product.jpg" class="card-img-top" alt="Product">
  <div class="card-header text-muted small">Category</div>
  <div class="card-body">
    <h5 class="card-title">Product Name</h5>
    <p class="card-text">Short description of the product.</p>
    <a href="#" class="btn btn-primary">Buy Now</a>
  </div>
  <div class="card-footer text-muted">$29.99</div>
</div>

<!-- Image overlay card -->
<div class="card text-white">
  <img src="hero.jpg" class="card-img" alt="Hero">
  <div class="card-img-overlay d-flex align-items-end">
    <div>
      <h5 class="card-title">Overlay Title</h5>
      <p class="card-text">Overlay text on the image.</p>
    </div>
  </div>
</div>

Alerts use .alert-{variant} for color, and .alert-dismissible plus a close button for JavaScript-powered dismissal. Link elements inside alerts use .alert-link for matching color. Show/hide alerts dynamically with the Bootstrap Alert JS API.

html
<!-- Static alerts -->
<div class="alert alert-success">Order placed successfully!</div>
<div class="alert alert-danger">Payment failed. <a href="#" class="alert-link">Try again</a></div>
<div class="alert alert-warning">Your session will expire in 5 minutes.</div>

<!-- Dismissible alert -->
<div class="alert alert-info alert-dismissible fade show" role="alert">
  <i class="bi bi-info-circle me-2"></i>
  New version available. <strong>Refresh to update.</strong>
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>

<!-- JS: show alert dynamically -->
<script>
function showAlert(msg, type = 'success') {
  const div = Object.assign(document.createElement('div'), {
    className: `alert alert-${type} alert-dismissible fade show`,
    innerHTML: `${msg}`
  });
  document.getElementById('alerts').appendChild(div);
}
</script>

Badges are inline elements styled with .badge plus a background color class. Positioned on buttons or icons they show notification counts. Use .rounded-pill for the pill shape. Bootstrap 5.3 adds bg-*-subtle for soft-color badges.

html
<!-- Inline badges -->
<h4>Inbox <span class="badge bg-danger">12</span></h4>
<h4>Messages <span class="badge bg-primary rounded-pill">99+</span></h4>

<!-- Button with badge -->
<button type="button" class="btn btn-primary position-relative">
  Cart
  <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
    5
    <span class="visually-hidden">items in cart</span>
  </span>
</button>

<!-- Soft-color status badges (BS 5.3) -->
<span class="badge bg-success-subtle text-success-emphasis">Active</span>
<span class="badge bg-warning-subtle text-warning-emphasis">Pending</span>
<span class="badge bg-danger-subtle text-danger-emphasis">Cancelled</span>

Progress bars use a container .progress wrapping .progress-bar. Set width with inline style="width:X%" and matching aria-valuenow. Add .progress-bar-striped and .progress-bar-animated for a striped animation. Stack multiple bars in one container.

html
<!-- Basic progress bar -->
<div class="progress" style="height:8px">
  <div class="progress-bar bg-primary" style="width:65%"
       role="progressbar" aria-valuenow="65" aria-valuemin="0" aria-valuemax="100">
  </div>
</div>

<!-- Animated striped -->
<div class="progress mt-3">
  <div class="progress-bar progress-bar-striped progress-bar-animated bg-success"
       style="width:75%">75%</div>
</div>

<!-- Stacked progress bars -->
<div class="progress mt-3">
  <div class="progress-bar bg-primary"    style="width:35%">HTML</div>
  <div class="progress-bar bg-success"    style="width:25%">CSS</div>
  <div class="progress-bar bg-warning"    style="width:15%">JS</div>
</div>

Bootstrap provides two spinner types: .spinner-border (rotating ring) and .spinner-grow (pulsing dot). Size with spinner-border-sm for inline use inside buttons. Color with text utilities. Always add a visually-hidden label for screen readers.

html
<!-- Border spinner -->
<div class="spinner-border text-primary" role="status">
  <span class="visually-hidden">Loading...</span>
</div>

<!-- Grow spinner -->
<div class="spinner-grow text-success" role="status">
  <span class="visually-hidden">Loading...</span>
</div>

<!-- Small spinner inside a button -->
<button class="btn btn-primary" id="submitBtn">
  <span class="spinner-border spinner-border-sm me-2 d-none" id="spin"></span>
  Submit
</button>

<script>
document.getElementById('submitBtn').addEventListener('click', function() {
  document.getElementById('spin').classList.remove('d-none');
  this.disabled = true;
});
</script>

Toasts are lightweight notifications that appear in a corner and auto-dismiss after a timeout. They require JavaScript initialization. Stack multiple toasts in a .toast-container positioned with utility classes. Set delay in milliseconds via data-bs-delay.

html
<!-- Toast container (fixed to corner) -->
<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <div id="myToast" class="toast align-items-center text-bg-success border-0" role="alert"
       data-bs-delay="4000">
    <div class="d-flex">
      <div class="toast-body">
        <i class="bi bi-check-circle me-2"></i> Changes saved successfully!
      </div>
      <button type="button" class="btn-close btn-close-white me-2 m-auto"
              data-bs-dismiss="toast"></button>
    </div>
  </div>
</div>

<script>
// Show toast programmatically
function showToast(id) {
  const toast = bootstrap.Toast.getOrCreateInstance(document.getElementById(id));
  toast.show();
}
showToast('myToast');
</script>

List groups turn <ul><li> or <div><a> into styled lists with borders. Add .list-group-item-action for hover/click states, .active for the selected state, and .list-group-item-{color} for contextual colors. Flush variant removes the outer border.

html
<!-- Basic list group -->
<ul class="list-group">
  <li class="list-group-item active">Active item</li>
  <li class="list-group-item">A second item</li>
  <li class="list-group-item list-group-item-success">Success item</li>
  <li class="list-group-item list-group-item-danger">Danger item</li>
</ul>

<!-- Linked list group (navigation) -->
<div class="list-group list-group-flush">
  <a href="#" class="list-group-item list-group-item-action active">Dashboard</a>
  <a href="#" class="list-group-item list-group-item-action">Orders</a>
  <a href="#" class="list-group-item list-group-item-action">
    Messages <span class="badge bg-primary float-end">3</span>
  </a>
</div>
Navigation Components

The Navbar collapses its links behind a hamburger button on small screens. The toggler button references the collapsible element by ID via data-bs-target. Choose when it expands with navbar-expand-{breakpoint}. Position with fixed-top, sticky-top, or fixed-bottom.

html
<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container">
    <a class="navbar-brand" href="#">MyApp</a>

    <button class="navbar-toggler" type="button"
            data-bs-toggle="collapse" data-bs-target="#navMenu">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navMenu">
      <ul class="navbar-nav me-auto">
        <li class="nav-item"><a class="nav-link active" href="#">Home</a></li>
        <li class="nav-item"><a class="nav-link" href="#">About</a></li>
      </ul>
      <form class="d-flex gap-2">
        <input class="form-control" type="search" placeholder="Search">
        <button class="btn btn-outline-primary" type="submit">Search</button>
      </form>
    </div>
  </div>
</nav>

Add .nav-tabs or .nav-pills to a .nav for styled tab navigation. Connect to tab content panes with data-bs-toggle="tab" and matching id/data-bs-target. Bootstrap handles show/hide and active states automatically.

html
<!-- Nav tabs -->
<ul class="nav nav-tabs" id="myTab">
  <li class="nav-item">
    <button class="nav-link active" data-bs-toggle="tab" data-bs-target="#home">Home</button>
  </li>
  <li class="nav-item">
    <button class="nav-link" data-bs-toggle="tab" data-bs-target="#profile">Profile</button>
  </li>
</ul>

<div class="tab-content border border-top-0 p-3">
  <div class="tab-pane fade show active" id="home">Home content</div>
  <div class="tab-pane fade" id="profile">Profile content</div>
</div>

<!-- Nav pills (same structure, different class) -->
<ul class="nav nav-pills gap-1">
  <li class="nav-item"><button class="nav-link active" data-bs-toggle="pill" data-bs-target="#p1">Overview</button></li>
  <li class="nav-item"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#p2">Details</button></li>
</ul>

Dropdowns wrap a toggle button and a .dropdown-menu. The toggler uses data-bs-toggle="dropdown". Popper.js positions the menu automatically. Dropdowns work in navbars, button groups, and standalone. Add dividers, headers, and disabled items with utility classes.

html
<div class="dropdown">
  <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
    Actions
  </button>
  <ul class="dropdown-menu">
    <li><h6 class="dropdown-header">Options</h6></li>
    <li><a class="dropdown-item" href="#"><i class="bi bi-pencil me-2"></i>Edit</a></li>
    <li><a class="dropdown-item" href="#"><i class="bi bi-files me-2"></i>Duplicate</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item text-danger" href="#"><i class="bi bi-trash me-2"></i>Delete</a></li>
  </ul>
</div>

<!-- Dropdown direction variants -->
<div class="dropup"><!-- opens upward --></div>
<div class="dropend"><!-- opens to the right --></div>

Bootstrap breadcrumbs use an <ol> with .breadcrumb. Dividers are added via CSS ::before pseudo-elements using a CSS variable — change the divider character without touching HTML.

html
<!-- Default breadcrumb (divider: /) -->
<nav aria-label="breadcrumb">
  <ol class="breadcrumb">
    <li class="breadcrumb-item"><a href="#">Home</a></li>
    <li class="breadcrumb-item"><a href="#">Products</a></li>
    <li class="breadcrumb-item active" aria-current="page">Laptop Pro</li>
  </ol>
</nav>

<!-- Custom divider via CSS variable -->
<style>
  .breadcrumb { --bs-breadcrumb-divider: '›'; }
  /* or SVG: --bs-breadcrumb-divider: url("data:image/svg+xml,..."); */
</style>

<!-- With icons -->
<nav aria-label="breadcrumb">
  <ol class="breadcrumb">
    <li class="breadcrumb-item"><a href="#"><i class="bi bi-house-door"></i></a></li>
    <li class="breadcrumb-item"><a href="#">Products</a></li>
    <li class="breadcrumb-item active">Detail</li>
  </ol>
</nav>

Pagination uses a <nav> wrapping a <ul class="pagination">. Items are .page-item with .page-link anchors. Mark the current page with .active and unavailable pages with .disabled. Size with .pagination-sm or .pagination-lg.

html
<nav aria-label="Page navigation">
  <ul class="pagination justify-content-center">
    <li class="page-item disabled">
      <a class="page-link" href="#"><i class="bi bi-chevron-left"></i></a>
    </li>
    <li class="page-item"><a class="page-link" href="#">1</a></li>
    <li class="page-item active"><a class="page-link" href="#">2</a></li>
    <li class="page-item"><a class="page-link" href="#">3</a></li>
    <li class="page-item">
      <a class="page-link" href="#"><i class="bi bi-chevron-right"></i></a>
    </li>
  </ul>
</nav>

Offcanvas creates a sidebar drawer that slides in from any edge. Trigger it with data-bs-toggle="offcanvas" pointing to the offcanvas element’s ID. Choose position with .offcanvas-start, -end, -top, -bottom. Use for mobile navigation, filter panels, and shopping carts.

html
<button class="btn btn-primary" data-bs-toggle="offcanvas" data-bs-target="#cart">
  <i class="bi bi-cart3"></i> Cart
</button>

<div class="offcanvas offcanvas-end" id="cart" tabindex="-1">
  <div class="offcanvas-header border-bottom">
    <h5 class="offcanvas-title">Shopping Cart</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas"></button>
  </div>
  <div class="offcanvas-body">
    <div class="d-flex gap-3 mb-3">
      <img src="product.jpg" width="64" class="rounded">
      <div>
        <p class="mb-0 fw-medium">Widget Pro</p>
        <p class="text-muted small">$49.99 × 2</p>
      </div>
    </div>
    <div class="mt-auto">
      <button class="btn btn-primary w-100">Checkout $99.98</button>
    </div>
  </div>
</div>

The Accordion uses Collapse under the hood. Each item has a header button (data-bs-toggle="collapse") targeting a .collapse panel. Adding data-bs-parent to each panel pointing to the accordion ID closes siblings when one opens.

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">
        What is your return policy?
      </button>
    </h2>
    <div id="faq1" class="accordion-collapse collapse show"
         data-bs-parent="#faqAccordion">
      <div class="accordion-body">
        30-day returns on all orders. Items must be unused and in original packaging.
      </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">
        How long does shipping take?
      </button>
    </h2>
    <div id="faq2" class="accordion-collapse collapse"
         data-bs-parent="#faqAccordion">
      <div class="accordion-body">3–5 business days standard, 1–2 express.</div>
    </div>
  </div>
</div>

Tooltips show a small text label on hover; popovers show a larger panel with a title and body. Both require JavaScript initialization (opt-in, not automatic). Popper.js positions them intelligently to avoid viewport clipping. Initialize all at once with a querySelectorAll loop.

html
<!-- Tooltip (title attr = tooltip text) -->
<button class="btn btn-secondary" data-bs-toggle="tooltip"
        data-bs-placement="top" title="Click to save your changes">
  Save
</button>

<!-- Popover (richer content) -->
<button class="btn btn-info" data-bs-toggle="popover"
        data-bs-placement="right"
        data-bs-title="Pro Tip"
        data-bs-content="Use keyboard shortcut Ctrl+S to save quickly.">
  <i class="bi bi-question-circle"></i>
</button>

<!-- Initialize all tooltips and popovers -->
<script>
document.querySelectorAll('[data-bs-toggle="tooltip"]')
  .forEach(el => new bootstrap.Tooltip(el));
document.querySelectorAll('[data-bs-toggle="popover"]')
  .forEach(el => new bootstrap.Popover(el));
</script>
Forms

Apply .form-control to text inputs, textareas, and file inputs. Selects get .form-select. Wrap each field in a .mb-3 div with a <label class="form-label"> above it. Use form-control-sm and form-control-lg for size variants.

html
<form>
  <div class="mb-3">
    <label for="nameInput" class="form-label">Full Name</label>
    <input type="text" id="nameInput" class="form-control" placeholder="Alice Smith">
  </div>

  <div class="mb-3">
    <label for="roleSelect" class="form-label">Role</label>
    <select id="roleSelect" class="form-select">
      <option value="">Choose role...</option>
      <option>Admin</option>
      <option>User</option>
    </select>
  </div>

  <div class="mb-3">
    <label for="bio" class="form-label">Bio</label>
    <textarea id="bio" class="form-control" rows="3"></textarea>
    <div class="form-text">Max 300 characters.</div>
  </div>

  <button type="submit" class="btn btn-primary">Save</button>
</form>

Wrap an <input> and <label> in a .form-floating div. The label must come after the input in the HTML (CSS uses the adjacent sibling combinator). Add a placeholder attribute to the input (required for the CSS trick to work).

html
<!-- Floating label input -->
<div class="form-floating mb-3">
  <input type="email" id="emailFloat" class="form-control" placeholder="name@example.com">
  <label for="emailFloat">Email address</label>
</div>

<!-- Floating label select -->
<div class="form-floating mb-3">
  <select id="countryFloat" class="form-select">
    <option value="">Select country</option>
    <option>United States</option>
    <option>Israel</option>
  </select>
  <label for="countryFloat">Country</label>
</div>

<!-- Floating textarea -->
<div class="form-floating">
  <textarea class="form-control" id="msgFloat" placeholder="Your message" style="height:120px"></textarea>
  <label for="msgFloat">Message</label>
</div>

Input groups use .input-group to attach .input-group-text add-ons, buttons, or dropdowns to any side of an input. Combine with .input-group-sm/-lg for size variants. Multiple add-ons and multiple inputs are supported.

html
<!-- Text prepend -->
<div class="input-group mb-3">
  <span class="input-group-text">@</span>
  <input type="text" class="form-control" placeholder="Username">
</div>

<!-- Currency input -->
<div class="input-group mb-3">
  <span class="input-group-text">$</span>
  <input type="number" class="form-control" placeholder="0.00">
  <span class="input-group-text">USD</span>
</div>

<!-- Search with button -->
<div class="input-group mb-3">
  <input type="search" class="form-control" placeholder="Search products...">
  <button class="btn btn-primary"><i class="bi bi-search"></i></button>
</div>

<!-- Dropdown append -->
<div class="input-group">
  <input type="text" class="form-control">
  <button class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">Format</button>
  <ul class="dropdown-menu dropdown-menu-end">
    <li><a class="dropdown-item" href="#">PDF</a></li>
    <li><a class="dropdown-item" href="#">CSV</a></li>
  </ul>
</div>

Add .needs-validation to a form and prevent default submission to trigger browser validation. Bootstrap uses .was-validated on the form to show .valid-feedback and .invalid-feedback elements. Or add .is-valid/.is-invalid classes manually for server-side validation.

html
<form class="needs-validation" id="myForm" novalidate>
  <div class="mb-3">
    <label class="form-label">Email</label>
    <input type="email" class="form-control" required>
    <div class="valid-feedback">Looks good!</div>
    <div class="invalid-feedback">Please provide a valid email.</div>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>

<script>
document.getElementById('myForm').addEventListener('submit', e => {
  if (!e.target.checkValidity()) {
    e.preventDefault();
    e.stopPropagation();
  }
  e.target.classList.add('was-validated');
});
</script>

<!-- Server-side: add class manually -->
<input class="form-control is-invalid">
<div class="invalid-feedback">Email already in use.</div>

Wrap each <input type="checkbox"> or <input type="radio"> with a .form-check div. Add .form-check-input to the input and .form-check-label to the label. Switches use role="switch" on the input inside a .form-switch container.

html
<!-- Checkbox -->
<div class="form-check">
  <input class="form-check-input" type="checkbox" id="agree" checked>
  <label class="form-check-label" for="agree">I agree to the terms</label>
</div>

<!-- Radio group -->
<div class="form-check">
  <input class="form-check-input" type="radio" name="size" id="sm" value="sm">
  <label class="form-check-label" for="sm">Small</label>
</div>
<div class="form-check">
  <input class="form-check-input" type="radio" name="size" id="lg" value="lg">
  <label class="form-check-label" for="lg">Large</label>
</div>

<!-- Toggle switch -->
<div class="form-check form-switch">
  <input class="form-check-input" type="checkbox" role="switch" id="darkMode">
  <label class="form-check-label" for="darkMode">Dark Mode</label>
</div>

Range inputs use .form-range. File inputs use .form-control — Bootstrap styles the file button automatically. Add multiple for multiple file selection. Show selected filename via JavaScript in a custom display area.

html
<!-- Range slider -->
<div class="mb-3">
  <label for="priceRange" class="form-label">
    Max Price: <span id="priceVal">500</span>
  </label>
  <input type="range" class="form-range" id="priceRange"
         min="0" max="1000" step="10" value="500"
         oninput="document.getElementById('priceVal').textContent=this.value">
</div>

<!-- File input -->
<div class="mb-3">
  <label for="avatar" class="form-label">Profile Photo</label>
  <input type="file" class="form-control" id="avatar" accept="image/*">
</div>

<!-- Multiple file upload -->
<div class="mb-3">
  <label for="docs" class="form-label">Documents</label>
  <input type="file" class="form-control" id="docs" multiple>
</div>

Inline forms use flexbox utilities to place fields side by side. Horizontal forms use the grid to put labels left of inputs. Use col-form-label on horizontal labels for proper vertical alignment with the input.

html
<!-- Inline form -->
<form class="d-flex gap-2 align-items-center">
  <input type="email" class="form-control" placeholder="Email">
  <input type="password" class="form-control" placeholder="Password">
  <button class="btn btn-primary">Login</button>
</form>

<!-- Horizontal form -->
<form class="mt-4">
  <div class="row mb-3">
    <label for="hEmail" class="col-sm-3 col-form-label">Email</label>
    <div class="col-sm-9">
      <input type="email" id="hEmail" class="form-control">
    </div>
  </div>
  <div class="row mb-3">
    <label for="hRole" class="col-sm-3 col-form-label">Role</label>
    <div class="col-sm-9">
      <select id="hRole" class="form-select">
        <option>Admin</option>
        <option>User</option>
      </select>
    </div>
  </div>
</form>

Modals overlay the page with a dialog. Trigger via data-bs-toggle="modal" or JavaScript. Modals have a header, body, and footer. Use modal-lg/modal-sm/modal-xl for size, modal-fullscreen for full page, and modal-dialog-scrollable for long content.

html
<button class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#confirmDelete">
  Delete Item
</button>

<div class="modal fade" id="confirmDelete" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Confirm Delete</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
        Are you sure you want to delete this item? This action cannot be undone.
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-danger">Delete</button>
      </div>
    </div>
  </div>
</div>
Utilities — Spacing & Display

Bootstrap generates margin and padding classes from a Sass map where the key multiplied by $spacer (default 1rem) gives the final value: 0=0, 1=0.25rem, 2=0.5rem, 3=1rem, 4=1.5rem, 5=3rem. The auto value maps to CSS auto.

html
<!-- mt-3 = margin-top: 1rem -->
<div class="mt-3 mb-2 px-4 py-1">Spaced box</div>

<!-- mx-auto centers a block element -->
<div class="w-50 mx-auto border p-3">Centered 50% width</div>

<!-- Negative margins (Sass $enable-negative-margins: true) -->
<div class="mt-n2">Pulls up by 0.5rem</div>

Insert a breakpoint infix between the property shorthand and the size: mt-0 mt-md-3 means no top margin below md, then 1rem at md and above. Bootstrap generates all combinations via its Sass loops.

html
<!-- No padding on mobile, 2rem on desktop -->
<section class="p-0 p-lg-5">
  <div class="mb-2 mb-md-4 mb-xl-5">
    Grows spacing at each tier
  </div>
</section>

<!-- Responsive gap in a flex container -->
<div class="d-flex gap-2 gap-md-4">
  <div>A</div>
  <div>B</div>
</div>

d-{value} sets display unconditionally; d-{breakpoint}-{value} applies from that breakpoint up. Combine a hide class with a show class to toggle visibility across viewports.

html
<!-- Hidden on mobile, block on md+ -->
<div class="d-none d-md-block">Desktop only</div>

<!-- Visible only on mobile -->
<div class="d-block d-md-none">Mobile only</div>

<!-- Flex only on large screens -->
<div class="d-none d-lg-flex gap-3">
  <span>Item A</span>
  <span>Item B</span>
</div>

.invisible sets visibility:hidden — the element still occupies layout space but is not visible. .d-none removes it from layout entirely. For screen readers, .visually-hidden hides visually but keeps the element in the accessibility tree.

html
<!-- Invisible but holds space -->
<div class="invisible">Placeholder</div>

<!-- Screen-reader-only label -->
<span class="visually-hidden">Loading results</span>

<!-- Toggle visibility via JS -->
<div id="overlay" class="visible">Content</div>
<script>
  document.getElementById('overlay').classList.toggle('invisible');
</script>

Bootstrap provides overflow-auto, overflow-hidden, overflow-visible, overflow-scroll, and axis-specific variants like overflow-x-auto. Apply them to containers with fixed dimensions to control scrolling.

html
<!-- Scrollable code/log box -->
<div class="overflow-auto" style="max-height:200px;">
  <pre>Very long content...</pre>
</div>

<!-- Clip overflowing badge -->
<div class="position-relative overflow-hidden" style="height:60px;">
  <span class="badge bg-danger position-absolute top-0 end-0">New</span>
</div>

<!-- Horizontal scroll for wide table -->
<div class="overflow-x-auto">
  <table class="table">...</table>
</div>

Bootstrap generates width/height utilities in steps of 25 (w-25, w-50, w-75, w-100, w-auto) and viewport variants (vw-100, min-vw-100). These are %-based relative to the parent.

html
<!-- Half-width card -->
<div class="w-50 border p-3">50% of parent</div>

<!-- Full viewport height hero -->
<section class="vh-100 d-flex align-items-center">
  <h1>Full-height hero</h1>
</section>

<!-- Auto width inline element -->
<button class="btn btn-primary w-auto">Auto</button>
<button class="btn btn-secondary w-100">Full width</button>

Bootstrap’s position utilities map to CSS position values. Edge utilities (top-0, end-50, bottom-100) use % values from 0–100. The translate-middle utility centers an absolutely-positioned element over its anchor.

html
<!-- Notification badge pinned to corner -->
<div class="position-relative d-inline-block">
  <i class="bi bi-bell fs-4"></i>
  <span class="position-absolute top-0 start-100 translate-middle
               badge rounded-pill bg-danger">3</span>
</div>

<!-- Sticky footer -->
<footer class="position-fixed bottom-0 start-0 w-100 bg-dark text-white p-2">
  &copy; 2024
</footer>

Bootstrap ships text alignment, transformation, weight, style, decoration, size, and line-height utilities. text-truncate clips overflow with an ellipsis and requires d-block or d-inline-block plus a fixed width to work.

html
<!-- Truncate long title -->
<p class="text-truncate" style="max-width:200px;">
  A very long title that exceeds the container width
</p>

<!-- Weight, size, and line-height -->
<p class="fw-bold fs-5 lh-lg">Bold large relaxed</p>
<p class="fw-light fst-italic text-muted">Light italic muted</p>

<!-- Responsive alignment -->
<p class="text-center text-md-start">Center on mobile</p>
Flexbox Utilities

d-flex sets display:flex. All flex child utilities (justify-content-*, align-items-*, flex-wrap, gap, order) only work inside a flex container. Use d-inline-flex for an inline flex context.

html
<!-- Row of cards with gap -->
<div class="d-flex gap-3 p-3 bg-light">
  <div class="card p-3">Card 1</div>
  <div class="card p-3">Card 2</div>
  <div class="card p-3">Card 3</div>
</div>

<!-- Inline badge row -->
<span class="d-inline-flex align-items-center gap-2">
  <i class="bi bi-check-circle text-success"></i> Done
</span>

justify-content-{start|end|center|between|around|evenly} maps directly to CSS justify-content. Responsive variants like justify-content-md-between override at the specified breakpoint.

html
<!-- Spread nav items to edges -->
<nav class="d-flex justify-content-between align-items-center p-3">
  <a href="#" class="text-decoration-none fw-bold">Logo</a>
  <ul class="d-flex list-unstyled gap-3 mb-0">
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
  </ul>
</nav>

<!-- Centered buttons on mobile, spread on desktop -->
<div class="d-flex justify-content-center justify-content-md-between">
  <button class="btn btn-primary">Save</button>
  <button class="btn btn-secondary">Cancel</button>
</div>

align-items-* applies to all children; align-self-* overrides for a specific child. Values: start|end|center|baseline|stretch.

html
<!-- Vertically center mixed-height children -->
<div class="d-flex align-items-center gap-3 p-3" style="height:120px;background:#f8f9fa;">
  <div style="height:60px;background:#dee2e6;" class="p-2">Short</div>
  <div style="height:100px;background:#adb5bd;" class="p-2">Tall</div>
  <!-- Override for this child only -->
  <div class="align-self-start p-2 bg-primary text-white">Top</div>
</div>

flex-wrap enables wrapping (default is nowrap). flex-wrap-reverse wraps in reverse order. Combined with gap and flex-grow-1, you get a fluid tag/chip layout.

html
<!-- Tag cloud that wraps naturally -->
<div class="d-flex flex-wrap gap-2">
  <span class="badge bg-primary">JavaScript</span>
  <span class="badge bg-success">TypeScript</span>
  <span class="badge bg-info">React</span>
  <span class="badge bg-warning text-dark">Vue</span>
  <span class="badge bg-danger">Angular</span>
  <span class="badge bg-secondary">Node.js</span>
</div>

gap-{0..5} uses CSS gap which applies between children only — no bleeding edge space. row-gap-* and column-gap-* control each axis independently.

html
<!-- Grid of cards with gap -->
<div class="row g-4">
  <div class="col-md-4"><div class="card h-100 p-3">A</div></div>
  <div class="col-md-4"><div class="card h-100 p-3">B</div></div>
  <div class="col-md-4"><div class="card h-100 p-3">C</div></div>
</div>

<!-- Different row vs column gap -->
<div class="d-flex flex-wrap row-gap-2 column-gap-4">
  <span class="badge bg-primary">Tag 1</span>
  <span class="badge bg-secondary">Tag 2</span>
</div>

order-{0..5} and order-first/order-last change visual order via CSS order. DOM order (for accessibility and tab sequence) is unchanged. Use responsive variants to reorder at specific breakpoints.

html
<!-- Image-right on desktop, image-below on mobile -->
<div class="d-flex flex-column flex-md-row gap-4">
  <div class="order-2 order-md-1 flex-fill">
    <h2>Article content</h2>
    <p>Text...</p>
  </div>
  <div class="order-1 order-md-2">
    <img src="hero.jpg" class="img-fluid" alt="Hero">
  </div>
</div>

flex-grow-1 makes an item expand to fill available space. flex-shrink-0 prevents an item from shrinking below its content size. These are the most common flex-item sizing utilities.

html
<!-- Search bar: icon fixed, input expands, button fixed -->
<div class="d-flex align-items-center gap-2 p-2 border rounded">
  <i class="bi bi-search flex-shrink-0"></i>
  <input type="text" class="form-control border-0 flex-grow-1" placeholder="Search...">
  <button class="btn btn-primary flex-shrink-0">Go</button>
</div>

flex-column sets flex-direction:column, stacking children vertically. Combine with flex-md-row for a common mobile-stack / desktop-row pattern. flex-column-reverse reverses the order.

html
<!-- Sidebar layout: stacked on mobile, side-by-side on lg -->
<div class="d-flex flex-column flex-lg-row gap-4 min-vh-100">
  <aside class="flex-shrink-0" style="width:240px;">
    <nav class="d-flex flex-column gap-2">
      <a href="#" class="btn btn-outline-primary text-start">Dashboard</a>
      <a href="#" class="btn btn-outline-secondary text-start">Settings</a>
    </nav>
  </aside>
  <main class="flex-grow-1">Main content</main>
</div>
JavaScript Plugin API

Data attributes (data-bs-toggle, data-bs-target) auto-initialize plugins when Bootstrap’s bundle loads. JavaScript initialization gives you a plugin instance for programmatic control and event listening. Both approaches produce identical behavior; JS is needed when you generate content dynamically.

javascript
// Data-attribute: no JS needed
// <button data-bs-toggle="modal" data-bs-target="#myModal">Open</button>

// JS initialization for programmatic control
const modalEl = document.getElementById('myModal');
const modal = new bootstrap.Modal(modalEl, { backdrop: 'static' });
modal.show();

// Get existing instance without creating a new one
const existing = bootstrap.Modal.getInstance(modalEl);
existing?.hide();

getInstance returns null if the plugin was never initialized. getOrCreateInstance initializes a new instance with default options if none exists. Use getInstance when you only want to interact with an already-active component.

javascript
const el = document.getElementById('myToast');

// Returns null if toast was never initialized
const maybeToast = bootstrap.Toast.getInstance(el);
maybeToast?.show(); // safe optional chaining

// Always returns an instance (creates if needed)
const toast = bootstrap.Toast.getOrCreateInstance(el, { delay: 3000 });
toast.show();

// Useful in event handlers after dynamic content load
document.querySelectorAll('.toast').forEach(t => {
  bootstrap.Toast.getOrCreateInstance(t).show();
});

Each plugin fires paired DOM events: show.bs.* (before transition, cancelable) and shown.bs.* (after transition). Listen on the component’s root element. Call event.preventDefault() on the show event to block the action.

javascript
const modalEl = document.getElementById('confirmModal');

// Block modal from opening if form is invalid
modalEl.addEventListener('show.bs.modal', (event) => {
  if (!document.getElementById('agreeCheckbox').checked) {
    event.preventDefault();
    alert('You must agree first.');
  }
});

// Focus first input after modal fully opens
modalEl.addEventListener('shown.bs.modal', () => {
  modalEl.querySelector('input')?.focus();
});

// Cleanup on hide
modalEl.addEventListener('hidden.bs.modal', () => {
  console.log('Modal closed, reset form here');
});

show()/hide()/toggle() control visibility. dispose() destroys the instance and removes all event listeners — call it before removing the DOM element to prevent memory leaks.

javascript
const modal = bootstrap.Modal.getOrCreateInstance('#confirmModal');

// Open on async action completion
async function deleteRecord(id) {
  await api.delete(id);
  modal.show();
}

// Auto-close after 3 seconds
modal.show();
setTimeout(() => modal.hide(), 3000);

// Full teardown when component unmounts
function unmount() {
  modal.dispose();
  document.getElementById('confirmModal').remove();
}

Data-attribute auto-initialization only runs at page load. For content injected afterward, use getOrCreateInstance after inserting the HTML, or query all new elements and initialize them in a loop.

javascript
async function loadWidget(containerId) {
  const res = await fetch('/api/widget-html');
  const html = await res.text();

  const container = document.getElementById(containerId);
  container.innerHTML = html;

  // Initialize all tooltips inside the newly injected HTML
  container.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
    bootstrap.Tooltip.getOrCreateInstance(el);
  });

  // Initialize any popovers too
  container.querySelectorAll('[data-bs-toggle="popover"]').forEach(el => {
    bootstrap.Popover.getOrCreateInstance(el);
  });
}

Listen for the show.bs.* (or hide.bs.*) event and call event.preventDefault() before the transition starts. This works for all Bootstrap plugins that fire cancelable events.

javascript
const offcanvasEl = document.getElementById('sidebar');

offcanvasEl.addEventListener('show.bs.offcanvas', async (event) => {
  event.preventDefault(); // stop default open transition

  const hasPermission = await checkUserPermission();
  if (hasPermission) {
    // Manually show after async check
    bootstrap.Offcanvas.getInstance(offcanvasEl)._isShown = false;
    bootstrap.Offcanvas.getInstance(offcanvasEl).show();
  } else {
    alert('Access denied');
  }
});

Use bootstrap.Collapse instances to show/hide panels without triggering button clicks. Pass { toggle: false } to initialize without toggling immediately.

javascript
// Open a specific accordion panel programmatically
function openPanel(panelId) {
  // Close all panels in the accordion
  document.querySelectorAll('#myAccordion .accordion-collapse').forEach(el => {
    bootstrap.Collapse.getOrCreateInstance(el, { toggle: false }).hide();
  });

  // Open the target panel
  const target = document.getElementById(panelId);
  bootstrap.Collapse.getOrCreateInstance(target, { toggle: false }).show();
}

// Expand all (remove data-bs-parent to allow multiple open)
document.querySelectorAll('.accordion-collapse').forEach(el => {
  el.removeAttribute('data-bs-parent');
  bootstrap.Collapse.getOrCreateInstance(el).show();
});

Pass options to new bootstrap.Carousel(el, options): interval (ms between slides), ride ('carousel' to autoplay on load), wrap (loop), keyboard (arrow key support).

javascript
const carouselEl = document.getElementById('heroCarousel');
const carousel = new bootstrap.Carousel(carouselEl, {
  interval: 4000,   // 4 seconds between slides
  ride: 'carousel', // autoplay immediately
  wrap: true,       // loop back to first slide
  keyboard: true    // arrow key navigation
});

// Go to a specific slide (0-indexed)
carousel.to(2);

// Pause on user hover (already default behavior)
carouselEl.addEventListener('mouseenter', () => carousel.pause());
carouselEl.addEventListener('mouseleave', () => carousel.cycle());

// React to slide change
carouselEl.addEventListener('slid.bs.carousel', (event) => {
  console.log('Now on slide:', event.to);
});
Customization with Sass

Bootstrap uses !default on all variables, meaning your assignment wins if it comes first. Import your overrides, then Bootstrap’s functions/variables/mixins/utilities, then Bootstrap itself.

scss
// custom.scss

// 1. Override variables BEFORE @use
$primary:    #7B2FBE;
$font-family-sans-serif: 'Inter', sans-serif;
$border-radius: 0.5rem;
$enable-negative-margins: true;

// 2. Import Bootstrap (with all defaults that haven't been overridden)
@import "bootstrap/scss/bootstrap";

// 3. Add your own component styles after
.btn-brand {
  background: $primary;
  color: #fff;
}

Merge your color into $theme-colors before the @import. Bootstrap then generates .btn-{name}, .bg-{name}, .text-{name}, and alert/badge variants automatically.

scss
// Add "brand" color to theme palette
$custom-colors: (
  "brand": #7B2FBE,
  "hot":   #FF4757
);

// Merge with Bootstrap's built-in theme colors
$theme-colors: map-merge($theme-colors, $custom-colors);

@import "bootstrap/scss/bootstrap";

// Usage in HTML after build:
// <button class="btn btn-brand">Brand</button>
// <div class="bg-hot text-white">Hot alert</div>

Bootstrap 5’s utility API (in _utilities.scss) is a Sass map. Merge additions or set individual utilities to null to disable them entirely, reducing output CSS size.

scss
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/utilities";

// Remove utilities you don't use
$utilities: map-remove($utilities, "float", "vertical-align");

// Add a custom utility
$utilities: map-merge($utilities, (
  "cursor": (
    property: cursor,
    class: cursor,
    values: (auto, pointer, grab)
  )
));

@import "bootstrap/scss/utilities/api";

Instead of @import "bootstrap", import only the partials you need. The required sequence: functions → variables → maps → mixins → root → reboot → your chosen components.

scss
// Required core (always include these)
@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";
@import "bootstrap/scss/reboot";

// Optional: only the components you use
@import "bootstrap/scss/type";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/nav";
@import "bootstrap/scss/navbar";
@import "bootstrap/scss/card";
@import "bootstrap/scss/modal";
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/utilities/api";

The $spacers map drives all m-* and p-* utility generation. Merge new keys before the utilities import to get additional size steps without touching Bootstrap’s source.

scss
$spacer: 1rem;

// Add steps 6 and 7 (4rem and 5rem)
$custom-spacers: (
  6: $spacer * 4,
  7: $spacer * 5
);

$spacers: map-merge(
  (0: 0, 1: $spacer * .25, 2: $spacer * .5,
   3: $spacer, 4: $spacer * 1.5, 5: $spacer * 3),
  $custom-spacers
);

@import "bootstrap/scss/bootstrap";

// Now use: <div class="mt-6 pb-7">...</div>

Bootstrap 5.3+ exposes component-level CSS variables (e.g., --bs-btn-bg, --bs-card-border-color). Override them in your stylesheet or inline to retheme individual instances without a Sass build.

css
/* Global primary color override (no Sass needed) */
:root {
  --bs-primary: #7B2FBE;
  --bs-primary-rgb: 123, 47, 190;
  --bs-link-color: #7B2FBE;
  --bs-link-hover-color: #5B1A9A;
}

/* Retheme one card instance */
.card.brand-card {
  --bs-card-bg: #EDE9FE;
  --bs-card-border-color: #7B2FBE;
  --bs-card-title-color: #5B1A9A;
}

Install Bootstrap’s npm package, import the Sass entry point from node_modules, and place your variable overrides before the import. Vite handles Sass natively with the sass package.

bash
npm install bootstrap @popperjs/core
npm install -D sass
scss
// src/styles/main.scss
$primary: #7B2FBE;
$border-radius: 0.6rem;
@import "bootstrap/scss/bootstrap";
javascript
// src/main.js
import './styles/main.scss';
import 'bootstrap'; // JS bundle

Set responsive: true in the utility map entry. Bootstrap’s API will generate breakpoint variants (gap-sm-2, gap-md-4, etc.) automatically alongside the base class.

scss
// After importing Bootstrap variables/maps/mixins/utilities:
$utilities: map-merge($utilities, (
  "grid-template-columns": (
    property: grid-template-columns,
    class: gtc,
    responsive: true,
    values: (
      1: repeat(1, 1fr),
      2: repeat(2, 1fr),
      3: repeat(3, 1fr),
      4: repeat(4, 1fr),
    )
  )
));

@import "bootstrap/scss/utilities/api";

// Usage: <div class="d-grid gtc-1 gtc-md-3"> </div>
Accessibility & Best Practices

Bootstrap sets the minimal required ARIA attributes automatically (aria-expanded, aria-controls, role="dialog" on modals). You should add aria-label or aria-labelledby to give components descriptive names for screen readers.

html
<!-- Modal with proper labeling -->
<div class="modal fade" id="deleteModal" tabindex="-1"
     aria-labelledby="deleteModalLabel" aria-describedby="deleteDesc">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="deleteModalLabel">Confirm Deletion</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"
                aria-label="Close"></button>
      </div>
      <div class="modal-body" id="deleteDesc">
        Are you sure? This action cannot be undone.
      </div>
    </div>
  </div>
</div>

.visually-hidden clips the element to a 1px square and removes it from the visual flow without removing it from the accessibility tree. Screen readers announce it; sighted users don’t see it. display:none hides from both.

html
<!-- Icon button with screen-reader label -->
<button class="btn btn-icon" aria-label="Search">
  <i class="bi bi-search" aria-hidden="true"></i>
  <span class="visually-hidden">Search the site</span>
</button>

<!-- Form field with visually-hidden label -->
<label for="email" class="visually-hidden">Email address</label>
<input type="email" id="email" class="form-control"
       placeholder="Email address">

<!-- Focusable skip link (shown on focus via visually-hidden-focusable) -->
<a href="#main" class="visually-hidden-focusable">Skip to main content</a>

Bootstrap’s Modal automatically moves focus inside the dialog on open and returns it to the trigger element on close. Override focus destination with the shown.bs.modal event. Never set tabindex="-1" on the modal’s interactive children.

javascript
const modalEl = document.getElementById('editModal');

// Focus first form field instead of close button
modalEl.addEventListener('shown.bs.modal', () => {
  const firstInput = modalEl.querySelector('input, textarea, select');
  firstInput?.focus();
});

// Return focus to a custom element (not the trigger) on close
const customTrigger = document.getElementById('openBtn');
modalEl.addEventListener('hidden.bs.modal', () => {
  customTrigger.focus();
});

WCAG 2.1 AA requires 4.5:1 for normal text and 3:1 for large text. Bootstrap’s color-contrast() Sass function auto-selects black or white text for backgrounds, but custom colors need manual verification.

scss
// Bootstrap uses color-contrast() internally:
// .btn-primary { color: color-contrast($primary); }

// Override the contrast threshold if needed
$min-contrast-ratio: 4.5; // default is 3.0 for AA large text

// For custom colors, use Bootstrap's function to compute safe text color
$my-bg: #7B2FBE;
$safe-text: color-contrast($my-bg); // returns #fff or #000

.custom-banner {
  background: $my-bg;
  color: $safe-text; // guaranteed readable
}

Bootstrap wraps transitions in @media (prefers-reduced-motion: reduce) blocks that collapse animation durations to near-zero. The global Sass variable $enable-transitions controls whether any transitions are generated at all.

scss
// Bootstrap applies this pattern globally:
@media (prefers-reduced-motion: reduce) {
  .fade { transition: none; }
  .carousel { .carousel-item { transition: none; } }
}

// Replicate the pattern in your own animated components
.hero-enter {
  animation: slideIn 0.4s ease;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
    opacity: 1;
  }
}

Bootstrap styles work on any element. Use semantic tags (<nav>, <main>, <article>, <header>) and apply Bootstrap classes to them. Avoid replacing semantic elements with <div> just to match example markup.

html
<header class="navbar navbar-expand-md bg-dark navbar-dark">
  <nav class="container-xl" aria-label="Main navigation">
    <a class="navbar-brand" href="/">MySite</a>
    <ul class="navbar-nav ms-auto">
      <li class="nav-item"><a class="nav-link" href="/about">About</a></li>
    </ul>
  </nav>
</header>
<main class="container py-5" id="main">
  <article class="card p-4">
    <h1>Article Title</h1>
  </article>
</main>

Bootstrap’s Collapse plugin updates aria-expanded on the trigger button automatically. aria-controls links the button to the panel it controls; screen readers announce “collapsed” or “expanded” as the user navigates.

html
<div class="accordion" id="faqAccordion">
  <div class="accordion-item">
    <h2 class="accordion-header" id="headingOne">
      <!-- Bootstrap sets aria-expanded to "true" when open -->
      <button class="accordion-button" type="button"
              data-bs-toggle="collapse"
              data-bs-target="#collapseOne"
              aria-expanded="false"
              aria-controls="collapseOne">
        Question text
      </button>
    </h2>
    <div id="collapseOne"
         class="accordion-collapse collapse"
         aria-labelledby="headingOne"
         data-bs-parent="#faqAccordion">
      <div class="accordion-body">Answer text.</div>
    </div>
  </div>
</div>

Add aria-label to the carousel, aria-label to each slide, set aria-current="true" on the active indicator, and add role="group" with a label to each slide. Pause autoplay on focus.

html
<div id="heroCarousel" class="carousel slide"
     aria-label="Product highlights" data-bs-ride="carousel">

  <div class="carousel-inner">
    <div class="carousel-item active"
         role="group" aria-label="Slide 1 of 3">
      <img src="slide1.jpg" class="d-block w-100" alt="Product A launch">
    </div>
    <div class="carousel-item"
         role="group" aria-label="Slide 2 of 3">
      <img src="slide2.jpg" class="d-block w-100" alt="Feature highlight">
    </div>
  </div>

  <button class="carousel-control-prev" type="button"
          data-bs-target="#heroCarousel" data-bs-slide="prev">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Previous slide</span>
  </button>
  <button class="carousel-control-next" type="button"
          data-bs-target="#heroCarousel" data-bs-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Next slide</span>
  </button>
</div>
Advanced Patterns & Real-World Usage

Bootstrap ships a separate RTL CSS build (bootstrap.rtl.min.css). Add dir="rtl" and lang="ar" (or relevant RTL language) to <html>, then use the RTL stylesheet. Logical properties like ms-auto (margin-start) automatically flip in RTL.

html
<!-- RTL HTML setup -->
<html lang="ar" dir="rtl">
<head>
  <!-- Use RTL build -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.rtl.min.css"
        rel="stylesheet">
</head>
<body>
  <nav class="navbar bg-dark navbar-dark">
    <!-- ms-auto becomes margin-right in RTL (pushes left) -->
    <ul class="navbar-nav ms-auto">
      <li class="nav-item"><a class="nav-link" href="#">الرئيسية</a></li>
    </ul>
  </nav>
</body>
</html>

Bootstrap utility classes use single-class selectors (specificity 0-1-0). Custom component styles using nested selectors or BEM can conflict. Solutions: add your styles after Bootstrap’s import, use CSS custom properties, or add the !important flag via the utility API’s print/important options.

css
/* Import Bootstrap first, then override */
/* @import "bootstrap/scss/bootstrap"; */

/* Use CSS layers to control specificity */
@layer bootstrap {
  /* Bootstrap goes here (or import inside layer) */
}

@layer components {
  /* Your styles always win over @layer bootstrap */
  .card-product {
    background: var(--brand-light);
    border-radius: 1rem;
  }
}

/* Or use CSS custom properties to retheme without fighting specificity */
.card-product {
  --bs-card-bg: #EDE9FE;
}

table-striped uses CSS :nth-child(odd) to alternate row backgrounds. table-hover highlights on hover. Wrap with table-responsive or table-responsive-{breakpoint} to add horizontal scroll on small screens.

html
<div class="table-responsive">
  <table class="table table-striped table-hover table-bordered align-middle">
    <thead class="table-dark">
      <tr>
        <th scope="col">#</th>
        <th scope="col">Name</th>
        <th scope="col">Status</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">1</th>
        <td>Alice</td>
        <td><span class="badge bg-success">Active</span></td>
      </tr>
    </tbody>
  </table>
</div>

The .ratio class uses the padding-bottom trick to create a fixed aspect ratio box. .ratio-16x9, .ratio-4x3, .ratio-1x1, and .ratio-21x9 are built in. The child element fills the box absolutely.

html
<!-- Responsive YouTube embed -->
<div class="ratio ratio-16x9">
  <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"
          title="Demo video"
          allowfullscreen></iframe>
</div>

<!-- Custom ratio via CSS variable -->
<div class="ratio" style="--bs-aspect-ratio: 56.25%">
  <video src="demo.mp4" controls></video>
</div>

.vstack is shorthand for d-flex flex-column; .hstack is shorthand for d-flex align-items-center. Use .vr (vertical rule) as a visual separator inside .hstack.

html
<!-- Vertical card stack -->
<div class="vstack gap-3">
  <div class="card p-3">Item 1</div>
  <div class="card p-3">Item 2</div>
  <div class="card p-3">Item 3</div>
</div>

<!-- Horizontal toolbar with separator -->
<div class="hstack gap-3 p-3 border rounded">
  <button class="btn btn-sm btn-outline-secondary">Bold</button>
  <div class="vr"></div>
  <button class="btn btn-sm btn-outline-secondary">Italic</button>
  <button class="btn btn-sm btn-outline-secondary">Underline</button>
  <div class="ms-auto"><button class="btn btn-sm btn-primary">Save</button></div>
</div>

Bootstrap generates d-print-{value} utilities that apply only inside @media print. Use d-print-none to hide navigation/ads in print, and d-none d-print-block to show print-only content.

html
<!-- Hide navbar and sidebar when printing -->
<header class="d-print-none">...navbar...</header>
<aside class="d-print-none">...sidebar...</aside>

<!-- Show print-only content (e.g., URL of links) -->
<div class="d-none d-print-block">
  <p>Printed from: https://mysite.com/report</p>
</div>

<!-- Force table to display as block for print -->
<div class="d-print-block">
  <table class="table">...full data table...</table>
</div>

object-fit-{contain|cover|fill|scale|none} maps to CSS object-fit. Pair with a fixed-height container so the utility has something to fit into. Use with object-position utilities to control the crop anchor.

html
<!-- Card image cropped to cover without distortion -->
<div class="card" style="width:300px;">
  <img src="product.jpg" class="card-img-top object-fit-cover"
       style="height:200px;" alt="Product">
  <div class="card-body">
    <h5 class="card-title">Product Name</h5>
  </div>
</div>

<!-- Logo image kept proportional within a fixed box -->
<div style="width:120px;height:60px;" class="border">
  <img src="logo.png" class="w-100 h-100 object-fit-contain" alt="Logo">
</div>

Bootstrap reserves a z-index scale for components: dropdowns (1000), sticky elements (1020), fixed (1030), offcanvas (1045), modal backdrop (1050), modal (1055), popover (1070), tooltip (1080). Override via Sass variables or CSS custom properties.

css
/* Override Bootstrap's z-index for custom sticky header */
:root {
  --bs-zindex-fixed: 1030;
}

/* Custom toast notification above modals */
.toast-container-top {
  z-index: 1090; /* above modal's 1055 */
  position: fixed;
  top: 1rem;
  right: 1rem;
}

/* Sass variable override (before Bootstrap import): */
/* $zindex-modal: 1055; */
/* $zindex-tooltip: 1080; */

The Offcanvas component slides in from any side (offcanvas-start, offcanvas-end, offcanvas-top, offcanvas-bottom). Use it with the responsive navbar pattern to replace the hamburger menu on mobile.

html
<nav class="navbar bg-dark navbar-dark">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">MySite</a>
    <button class="navbar-toggler" type="button"
            data-bs-toggle="offcanvas"
            data-bs-target="#mobileNav"
            aria-controls="mobileNav">
      <span class="navbar-toggler-icon"></span>
    </button>
  </div>
</nav>

<div class="offcanvas offcanvas-start text-bg-dark" id="mobileNav"
     tabindex="-1" aria-labelledby="mobileNavLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="mobileNavLabel">Menu</h5>
    <button type="button" class="btn-close btn-close-white"
            data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <ul class="navbar-nav">
      <li class="nav-item"><a class="nav-link" href="#">Home</a></li>
      <li class="nav-item"><a class="nav-link" href="#">About</a></li>
    </ul>
  </div>
</div>

Alerts are inline, persistent, and part of the document flow — ideal for form errors or page-level messages. Toasts are positioned overlays that auto-dismiss after a timeout — ideal for transient status messages triggered by user actions.

html
<!-- Toast container (fixed position) -->
<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <div id="saveToast" class="toast align-items-center text-bg-success border-0"
       role="alert" aria-live="assertive" aria-atomic="true">
    <div class="d-flex">
      <div class="toast-body">
        <i class="bi bi-check-circle me-2"></i>Changes saved!
      </div>
      <button type="button" class="btn-close btn-close-white me-2 m-auto"
              data-bs-dismiss="toast" aria-label="Close"></button>
    </div>
  </div>
</div>

<script>
async function saveData() {
  await api.save();
  bootstrap.Toast.getOrCreateInstance('#saveToast', { delay: 3000 }).show();
}
</script>

Bootstrap 5.3+ ships a built-in dark mode. Add data-bs-theme="dark" to <html> or any container. Toggle it with JavaScript. Components inside automatically retheme using Bootstrap’s CSS custom properties.

html
<html data-bs-theme="light">
<body>
  <button id="themeToggle" class="btn btn-outline-secondary">
    <i class="bi bi-moon-fill"></i> Dark Mode
  </button>

  <div class="card mt-4 p-4">
    <p>This card automatically adapts to the theme.</p>
  </div>

  <script>
    const toggle = document.getElementById('themeToggle');
    toggle.addEventListener('click', () => {
      const html = document.documentElement;
      const isDark = html.dataset.bsTheme === 'dark';
      html.dataset.bsTheme = isDark ? 'light' : 'dark';
      toggle.innerHTML = isDark
        ? '<i class="bi bi-moon-fill"></i> Dark Mode'
        : '<i class="bi bi-sun-fill"></i> Light Mode';
      localStorage.setItem('theme', html.dataset.bsTheme);
    });

    // Restore preference
    const saved = localStorage.getItem('theme');
    if (saved) document.documentElement.dataset.bsTheme = saved;
  </script>
</body>
</html>

A production layout layers the grid for page structure, flexbox utilities for component internals, and Bootstrap components for UI elements. The pattern: fixed navbar + sidebar + main content grid + responsive collapse for mobile.

html
<body class="bg-light">
  <!-- Fixed top navbar -->
  <nav class="navbar navbar-dark bg-dark fixed-top">
    <div class="container-fluid">
      <a class="navbar-brand fw-bold" href="#">Dashboard</a>
      <div class="d-flex align-items-center gap-3">
        <span class="badge bg-success">Live</span>
        <img src="avatar.jpg" width="32" height="32"
             class="rounded-circle object-fit-cover" alt="User">
      </div>
    </div>
  </nav>

  <div class="d-flex" style="margin-top:56px;min-height:calc(100vh - 56px);">
    <!-- Sidebar (hidden on mobile) -->
    <aside class="d-none d-md-flex flex-column bg-white border-end p-3"
           style="width:220px;flex-shrink:0;">
      <nav class="vstack gap-1">
        <a href="#" class="btn btn-primary text-start">
          <i class="bi bi-speedometer2 me-2"></i>Overview
        </a>
        <a href="#" class="btn btn-light text-start">
          <i class="bi bi-bar-chart me-2"></i>Analytics
        </a>
        <a href="#" class="btn btn-light text-start">
          <i class="bi bi-gear me-2"></i>Settings
        </a>
      </nav>
    </aside>

    <!-- Main content -->
    <main class="flex-grow-1 p-4">
      <!-- Stat cards row -->
      <div class="row g-4 mb-4">
        <div class="col-sm-6 col-xl-3">
          <div class="card border-0 shadow-sm h-100">
            <div class="card-body">
              <div class="d-flex justify-content-between align-items-start">
                <div>
                  <p class="text-muted small mb-1">Revenue</p>
                  <h3 class="fw-bold mb-0">$48,200</h3>
                </div>
                <div class="bg-success bg-opacity-10 p-2 rounded-3">
                  <i class="bi bi-currency-dollar text-success fs-5"></i>
                </div>
              </div>
              <p class="text-success small mt-2 mb-0">+12% vs last month</p>
            </div>
          </div>
        </div>
        <!-- ...more stat cards -->
      </div>

      <!-- Data table -->
      <div class="card border-0 shadow-sm">
        <div class="card-header bg-white d-flex justify-content-between">
          <h6 class="mb-0 fw-semibold">Recent Orders</h6>
          <button class="btn btn-sm btn-outline-primary">Export</button>
        </div>
        <div class="table-responsive">
          <table class="table table-hover mb-0 align-middle">
            <thead class="table-light">
              <tr>
                <th>Order</th><th>Customer</th><th>Status</th><th>Total</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>#1042</td>
                <td>Alice Smith</td>
                <td><span class="badge bg-success">Shipped</span></td>
                <td class="fw-semibold">$129.99</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </main>
  </div>
</body>
Prev
Next
Drag
Map
HTML Snippets Powered By : XYZScripts.com
Select the fields to be shown. Others will be hidden. Drag and drop to rearrange the order.
  • Image
  • SKU
  • Rating
  • Price
  • Stock
  • Availability
  • Add to cart
  • Description
  • Content
  • Weight
  • Dimensions
  • Additional information
Click outside to hide the comparison bar
Compare