Bootstrap 5
A mobile-first CSS framework for building responsive, modern web interfaces with pre-built components and utility classes.
Bootstrap 5 Cheatsheet
A mobile-first CSS framework for building responsive, modern web interfaces with pre-built components and utility classes.
Overview
Bootstrap 5 is the latest major release of the world's most popular front-end framework, featuring a redesigned grid system, new utility API, improved forms, and no jQuery dependency.
graph TB
subgraph "Bootstrap 5 Architecture"
A[Bootstrap 5] --> B[Layout]
A --> C[Content]
A --> D[Components]
A --> E[Utilities]
A --> F[Helpers]
B --> B1[Grid System]
B --> B2[Containers]
B --> B3[Breakpoints]
C --> C1[Typography]
C --> C2[Images]
C --> C3[Tables]
D --> D1[Buttons]
D --> D2[Cards]
D --> D3[Navbar]
D --> D4[Modals]
D --> D5[Forms]
E --> E1[Spacing]
E --> E2[Colours]
E --> E3[Display]
E --> E4[Flexbox]
end
Grid System
Key Concepts
The Bootstrap grid system uses a series of containers, rows, and columns to layout and align content. It's built with flexbox and is fully responsive.
graph TB
subgraph "Grid Hierarchy"
A[Container] --> B[Row]
B --> C1[Column 1]
B --> C2[Column 2]
B --> C3[Column 3]
end
subgraph "12-Column System"
D[Total: 12 Columns]
D --> E1[col-4]
D --> E2[col-4]
D --> E3[col-4]
end
Common Patterns
Container Types
<!-- Fixed-width container (max-width at each breakpoint) -->
<div class="container">...</div>
<!-- Fluid container (100% width at all breakpoints) -->
<div class="container-fluid">...</div>
<!-- Responsive containers (100% until breakpoint) -->
<div class="container-sm">...</div> <!-- 100% until sm -->
<div class="container-md">...</div> <!-- 100% until md -->
<div class="container-lg">...</div> <!-- 100% until lg -->
<div class="container-xl">...</div> <!-- 100% until xl -->
<div class="container-xxl">...</div> <!-- 100% until xxl -->
Basic Grid Structure
<!-- Equal-width columns -->
<div class="container">
<div class="row">
<div class="col">Column 1</div>
<div class="col">Column 2</div>
<div class="col">Column 3</div>
</div>
</div>
<!-- Specific column widths -->
<div class="container">
<div class="row">
<div class="col-4">4 columns</div>
<div class="col-8">8 columns</div>
</div>
</div>
<!-- Responsive columns -->
<div class="container">
<div class="row">
<div class="col-12 col-md-6 col-lg-4">
Full on mobile, half on tablet, third on desktop
</div>
</div>
</div>
Row Columns
<!-- Set number of columns in a row -->
<div class="row row-cols-2">
<div class="col">Item 1</div>
<div class="col">Item 2</div>
<div class="col">Item 3</div>
<div class="col">Item 4</div>
</div>
<!-- Responsive row columns -->
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-4">
<!-- Items will be 1/row on mobile, 2/row on tablet, 4/row on desktop -->
</div>
Gutters (Spacing Between Columns)
<!-- Horizontal gutters -->
<div class="row gx-5">...</div>
<!-- Vertical gutters -->
<div class="row gy-5">...</div>
<!-- Both horizontal and vertical -->
<div class="row g-3">...</div>
<!-- No gutters -->
<div class="row g-0">...</div>
Offsetting Columns
<!-- Offset columns -->
<div class="row">
<div class="col-md-4 offset-md-4">Centred column</div>
</div>
<!-- Margin utilities for offsetting -->
<div class="row">
<div class="col-md-4 ms-auto">Pushed to the right</div>
</div>
Examples
Responsive Card Layout
<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">
<div class="card-body">Card 1</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<div class="card-body">Card 2</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<div class="card-body">Card 3</div>
</div>
</div>
</div>
</div>
Sidebar Layout
<div class="container-fluid">
<div class="row">
<!-- Sidebar -->
<div class="col-md-3 col-lg-2 d-md-block bg-light sidebar">
<nav>Sidebar content</nav>
</div>
<!-- Main content -->
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
Main content
</main>
</div>
</div>
Responsive Breakpoints
Key Concepts
Bootstrap uses six default breakpoints for responsive design. These breakpoints are based on minimum viewport widths and allow scaling up as the viewport changes.
graph LR
A["xs<br/>< 576px"] --> B["sm<br/>≥ 576px"]
B --> C["md<br/>≥ 768px"]
C --> D["lg<br/>≥ 992px"]
D --> E["xl<br/>≥ 1200px"]
E --> F["xxl<br/>≥ 1400px"]
Breakpoint Values
| Breakpoint | Class infix | Dimensions |
|---|---|---|
| Extra small | None | <576px |
| Small | sm |
≥576px |
| Medium | md |
≥768px |
| Large | lg |
≥992px |
| Extra large | xl |
≥1200px |
| Extra extra large | xxl |
≥1400px |
Common Patterns
Responsive Classes
<!-- Display utilities -->
<div class="d-none d-md-block">Hidden on mobile, visible on tablet+</div>
<div class="d-block d-lg-none">Visible until large screens</div>
<!-- Text alignment -->
<p class="text-start text-md-center text-lg-end">
Left on mobile, centre on tablet, right on desktop
</p>
<!-- Flexbox direction -->
<div class="d-flex flex-column flex-md-row">
Vertical on mobile, horizontal on tablet+
</div>
<!-- Float -->
<div class="float-none float-md-start float-lg-end">
Responsive floating
</div>
Media Queries in Custom CSS
// Using Bootstrap's mixins
@include media-breakpoint-up(sm) { ... }
@include media-breakpoint-down(md) { ... }
@include media-breakpoint-between(sm, lg) { ... }
@include media-breakpoint-only(md) { ... }
// Raw media queries
@media (min-width: 576px) { ... } // sm
@media (min-width: 768px) { ... } // md
@media (min-width: 992px) { ... } // lg
@media (min-width: 1200px) { ... } // xl
@media (min-width: 1400px) { ... } // xxl
Utilities
Key Concepts
Bootstrap 5's utility classes provide quick styling without writing custom CSS. The new Utility API allows generating custom utilities.
Spacing Utilities
<!-- Margin: m{sides}-{size} -->
<!-- Padding: p{sides}-{size} -->
<!-- Sides: t(top), b(bottom), s(start), e(end), x(horizontal), y(vertical) -->
<!-- Sizes: 0, 1, 2, 3, 4, 5, auto -->
<div class="mt-3">Margin top 3</div>
<div class="mb-4">Margin bottom 4</div>
<div class="ms-2">Margin start (left in LTR) 2</div>
<div class="me-auto">Margin end auto</div>
<div class="mx-3">Margin horizontal 3</div>
<div class="my-5">Margin vertical 5</div>
<div class="p-3">Padding all sides 3</div>
<div class="px-4 py-2">Padding x:4, y:2</div>
<!-- Responsive spacing -->
<div class="mt-2 mt-md-4 mt-lg-5">Responsive margin top</div>
<!-- Gap for flexbox/grid -->
<div class="d-flex gap-3">Flex with gap</div>
Colour Utilities
<!-- Text colours -->
<p class="text-primary">Primary text</p>
<p class="text-secondary">Secondary text</p>
<p class="text-success">Success text</p>
<p class="text-danger">Danger text</p>
<p class="text-warning">Warning text</p>
<p class="text-info">Info text</p>
<p class="text-light bg-dark">Light text</p>
<p class="text-dark">Dark text</p>
<p class="text-muted">Muted text</p>
<p class="text-white bg-dark">White text</p>
<!-- Background colours -->
<div class="bg-primary text-white">Primary background</div>
<div class="bg-secondary">Secondary background</div>
<div class="bg-success">Success background</div>
<div class="bg-danger">Danger background</div>
<div class="bg-warning">Warning background</div>
<div class="bg-info">Info background</div>
<div class="bg-light">Light background</div>
<div class="bg-dark text-white">Dark background</div>
<div class="bg-transparent">Transparent background</div>
<!-- Background opacity -->
<div class="bg-primary bg-opacity-75">75% opacity</div>
<div class="bg-primary bg-opacity-50">50% opacity</div>
<div class="bg-primary bg-opacity-25">25% opacity</div>
Display Utilities
<!-- Display values -->
<div class="d-none">Hidden</div>
<div class="d-inline">Inline</div>
<div class="d-inline-block">Inline block</div>
<div class="d-block">Block</div>
<div class="d-grid">Grid</div>
<div class="d-table">Table</div>
<div class="d-flex">Flexbox</div>
<div class="d-inline-flex">Inline flexbox</div>
<!-- Print display -->
<div class="d-print-none">Hidden when printing</div>
<div class="d-none d-print-block">Only visible when printing</div>
Flexbox Utilities
<!-- Flex container -->
<div class="d-flex">Flex container</div>
<div class="d-inline-flex">Inline flex container</div>
<!-- Direction -->
<div class="d-flex flex-row">Horizontal (default)</div>
<div class="d-flex flex-row-reverse">Horizontal reversed</div>
<div class="d-flex flex-column">Vertical</div>
<div class="d-flex flex-column-reverse">Vertical reversed</div>
<!-- Justify content (main axis) -->
<div class="d-flex justify-content-start">Start</div>
<div class="d-flex justify-content-end">End</div>
<div class="d-flex justify-content-center">Centre</div>
<div class="d-flex justify-content-between">Space between</div>
<div class="d-flex justify-content-around">Space around</div>
<div class="d-flex justify-content-evenly">Space evenly</div>
<!-- Align items (cross axis) -->
<div class="d-flex align-items-start">Align start</div>
<div class="d-flex align-items-end">Align end</div>
<div class="d-flex align-items-center">Align centre</div>
<div class="d-flex align-items-baseline">Align baseline</div>
<div class="d-flex align-items-stretch">Align stretch</div>
<!-- Align self (individual item) -->
<div class="align-self-start">Self start</div>
<div class="align-self-center">Self centre</div>
<div class="align-self-end">Self end</div>
<!-- Flex wrap -->
<div class="d-flex flex-wrap">Wrap</div>
<div class="d-flex flex-nowrap">No wrap</div>
<div class="d-flex flex-wrap-reverse">Wrap reverse</div>
<!-- Flex grow/shrink -->
<div class="flex-grow-1">Grow</div>
<div class="flex-shrink-0">Don't shrink</div>
<!-- Order -->
<div class="order-0">First</div>
<div class="order-1">Second</div>
<div class="order-last">Last</div>
Other Common Utilities
<!-- Border -->
<div class="border">All borders</div>
<div class="border-top">Top border</div>
<div class="border-0">No border</div>
<div class="border border-primary">Primary colour border</div>
<div class="border border-2">Border width 2</div>
<div class="rounded">Rounded corners</div>
<div class="rounded-circle">Circle</div>
<div class="rounded-pill">Pill shape</div>
<!-- Sizing -->
<div class="w-25">Width 25%</div>
<div class="w-50">Width 50%</div>
<div class="w-75">Width 75%</div>
<div class="w-100">Width 100%</div>
<div class="w-auto">Width auto</div>
<div class="h-100">Height 100%</div>
<div class="mw-100">Max width 100%</div>
<div class="mh-100">Max height 100%</div>
<div class="min-vw-100">Min viewport width 100%</div>
<div class="min-vh-100">Min viewport height 100%</div>
<!-- Position -->
<div class="position-static">Static</div>
<div class="position-relative">Relative</div>
<div class="position-absolute">Absolute</div>
<div class="position-fixed">Fixed</div>
<div class="position-sticky">Sticky</div>
<!-- Top/Bottom/Start/End positioning -->
<div class="position-absolute top-0 start-0">Top left</div>
<div class="position-absolute top-50 start-50 translate-middle">Centred</div>
<!-- Shadow -->
<div class="shadow-none">No shadow</div>
<div class="shadow-sm">Small shadow</div>
<div class="shadow">Regular shadow</div>
<div class="shadow-lg">Large shadow</div>
<!-- Overflow -->
<div class="overflow-auto">Auto</div>
<div class="overflow-hidden">Hidden</div>
<div class="overflow-visible">Visible</div>
<div class="overflow-scroll">Scroll</div>
<!-- Visibility -->
<div class="visible">Visible</div>
<div class="invisible">Invisible (still takes space)</div>
<!-- Text -->
<p class="text-start">Left aligned</p>
<p class="text-center">Centre aligned</p>
<p class="text-end">Right aligned</p>
<p class="text-wrap">Wrap text</p>
<p class="text-nowrap">No wrap</p>
<p class="text-truncate">Truncate with ellipsis</p>
<p class="text-lowercase">lowercase</p>
<p class="text-uppercase">UPPERCASE</p>
<p class="text-capitalize">Capitalise</p>
<p class="fw-bold">Bold</p>
<p class="fw-normal">Normal weight</p>
<p class="fw-light">Light weight</p>
<p class="fst-italic">Italic</p>
<p class="text-decoration-none">No decoration</p>
<p class="text-decoration-underline">Underline</p>
<p class="text-decoration-line-through">Strikethrough</p>
<p class="fs-1">Font size 1 (largest)</p>
<p class="fs-6">Font size 6 (smallest)</p>
<p class="lh-1">Line height 1</p>
<p class="lh-sm">Small line height</p>
<p class="lh-base">Base line height</p>
<p class="lh-lg">Large line height</p>
Components
Buttons
<!-- Basic buttons -->
<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-secondary">Secondary</button>
<button type="button" class="btn btn-success">Success</button>
<button type="button" class="btn btn-danger">Danger</button>
<button type="button" class="btn btn-warning">Warning</button>
<button type="button" class="btn btn-info">Info</button>
<button type="button" class="btn btn-light">Light</button>
<button type="button" class="btn btn-dark">Dark</button>
<button type="button" class="btn btn-link">Link</button>
<!-- Outline buttons -->
<button type="button" class="btn btn-outline-primary">Outline Primary</button>
<button type="button" class="btn btn-outline-secondary">Outline Secondary</button>
<!-- Button sizes -->
<button type="button" class="btn btn-primary btn-lg">Large</button>
<button type="button" class="btn btn-primary">Default</button>
<button type="button" class="btn btn-primary btn-sm">Small</button>
<!-- Block button -->
<div class="d-grid gap-2">
<button class="btn btn-primary" type="button">Block button</button>
</div>
<!-- Disabled state -->
<button type="button" class="btn btn-primary" disabled>Disabled</button>
<!-- Button with spinner -->
<button class="btn btn-primary" type="button" disabled>
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Loading...
</button>
<!-- Button group -->
<div class="btn-group" role="group" aria-label="Button group">
<button type="button" class="btn btn-primary">Left</button>
<button type="button" class="btn btn-primary">Middle</button>
<button type="button" class="btn btn-primary">Right</button>
</div>
Cards
<!-- Basic card -->
<div class="card" style="width: 18rem;">
<img src="..." class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Card content goes here.</p>
<a href="#" class="btn btn-primary">Go somewhere</a>
</div>
</div>
<!-- Card with header and footer -->
<div class="card">
<div class="card-header">Featured</div>
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Content</p>
</div>
<div class="card-footer text-muted">2 days ago</div>
</div>
<!-- Card with list group -->
<div class="card">
<div class="card-header">Features</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Feature 1</li>
<li class="list-group-item">Feature 2</li>
<li class="list-group-item">Feature 3</li>
</ul>
</div>
<!-- Horizontal card -->
<div class="card mb-3" style="max-width: 540px;">
<div class="row g-0">
<div class="col-md-4">
<img src="..." class="img-fluid rounded-start" alt="...">
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Content</p>
</div>
</div>
</div>
</div>
<!-- Card colours -->
<div class="card text-white bg-primary mb-3">
<div class="card-body">Primary card</div>
</div>
<!-- Card grid -->
<div class="row row-cols-1 row-cols-md-3 g-4">
<div class="col">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">Card 1</h5>
</div>
</div>
</div>
<!-- More cards... -->
</div>
Navbar
<!-- Basic navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Brand</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">
<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>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Dark navbar (5.3+: use data-bs-theme="dark"; .navbar-dark is deprecated) -->
<nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark">
<!-- ... -->
</nav>
<!-- Navbar with dropdown -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Brand</a>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink"
role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<!-- Navbar with search -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Brand</a>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</nav>
<!-- Fixed navbar -->
<nav class="navbar fixed-top navbar-light bg-light">...</nav>
<nav class="navbar fixed-bottom bg-dark" data-bs-theme="dark">...</nav>
<nav class="navbar sticky-top navbar-light bg-light">...</nav>
Modals
<!-- Modal trigger button -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal"
data-bs-target="#exampleModal">
Launch modal
</button>
<!-- Modal structure -->
<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 body content here.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- Modal sizes -->
<div class="modal-dialog modal-sm">...</div> <!-- Small -->
<div class="modal-dialog">...</div> <!-- Default -->
<div class="modal-dialog modal-lg">...</div> <!-- Large -->
<div class="modal-dialog modal-xl">...</div> <!-- Extra large -->
<!-- Centred modal -->
<div class="modal-dialog modal-dialog-centered">...</div>
<!-- Scrollable modal -->
<div class="modal-dialog modal-dialog-scrollable">...</div>
<!-- Fullscreen modal -->
<div class="modal-dialog modal-fullscreen">...</div>
<div class="modal-dialog modal-fullscreen-sm-down">...</div>
<!-- Modal via JavaScript -->
<script>
const myModal = new bootstrap.Modal(document.getElementById('exampleModal'), {
keyboard: false,
backdrop: 'static'
});
myModal.show();
myModal.hide();
myModal.toggle();
</script>
Other Components
<!-- Alert -->
<div class="alert alert-primary" role="alert">Primary alert</div>
<div class="alert alert-success alert-dismissible fade show" role="alert">
Success alert!
<button type="button" class="btn-close" data-bs-dismiss="alert"
aria-label="Close"></button>
</div>
<!-- Badge -->
<span class="badge bg-primary">Primary</span>
<span class="badge rounded-pill bg-danger">99+</span>
<button type="button" class="btn btn-primary">
Notifications <span class="badge bg-secondary">4</span>
</button>
<!-- Breadcrumb -->
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item"><a href="#">Library</a></li>
<li class="breadcrumb-item active" aria-current="page">Data</li>
</ol>
</nav>
<!-- Progress bar -->
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: 25%;"
aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">25%</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-striped progress-bar-animated"
style="width: 75%"></div>
</div>
<!-- Spinner -->
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<div class="spinner-grow text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<!-- Toast -->
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">Bootstrap</strong>
<small>Just now</small>
<button type="button" class="btn-close" data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
<div class="toast-body">Hello, world!</div>
</div>
<!-- Accordion -->
<div class="accordion" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseOne" aria-expanded="true"
aria-controls="collapseOne">
Accordion Item #1
</button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse show"
aria-labelledby="headingOne" data-bs-parent="#accordionExample">
<div class="accordion-body">Content here</div>
</div>
</div>
</div>
<!-- Tabs -->
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="home-tab" 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" id="profile-tab" 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" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel"
aria-labelledby="home-tab">Home content</div>
<div class="tab-pane fade" id="profile" role="tabpanel"
aria-labelledby="profile-tab">Profile content</div>
</div>
<!-- Pagination -->
<nav aria-label="Page navigation">
<ul class="pagination">
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1">Previous</a>
</li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><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="#">Next</a>
</li>
</ul>
</nav>
<!-- Tooltip -->
<button type="button" class="btn btn-secondary" data-bs-toggle="tooltip"
data-bs-placement="top" title="Tooltip text">
Hover me
</button>
<script>
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl)
})
</script>
<!-- Popover -->
<button type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover"
title="Popover title" data-bs-content="Popover content">
Click me
</button>
Forms and Validation
Key Concepts
Bootstrap 5 forms feature a complete overhaul with floating labels, form controls, and enhanced validation styles.
Form Controls
<!-- Basic form -->
<form>
<!-- Text input -->
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email"
placeholder="name@example.com">
<div class="form-text">We'll never share your email.</div>
</div>
<!-- Password -->
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password">
</div>
<!-- Textarea -->
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea class="form-control" id="message" rows="3"></textarea>
</div>
<!-- Select -->
<div class="mb-3">
<label for="country" class="form-label">Country</label>
<select class="form-select" id="country">
<option selected>Choose...</option>
<option value="1">United Kingdom</option>
<option value="2">United States</option>
<option value="3">Australia</option>
</select>
</div>
<!-- Multiple select -->
<select class="form-select" multiple>
<option>Option 1</option>
<option>Option 2</option>
</select>
<!-- Checkbox -->
<div class="form-check">
<input class="form-check-input" type="checkbox" id="agree">
<label class="form-check-label" for="agree">
I agree to terms
</label>
</div>
<!-- Inline checkboxes -->
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="check1">
<label class="form-check-label" for="check1">1</label>
</div>
<!-- Radio buttons -->
<div class="form-check">
<input class="form-check-input" type="radio" name="options" id="option1">
<label class="form-check-label" for="option1">Option 1</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="options" id="option2">
<label class="form-check-label" for="option2">Option 2</label>
</div>
<!-- Switch -->
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="switch1">
<label class="form-check-label" for="switch1">Toggle switch</label>
</div>
<!-- Range -->
<div class="mb-3">
<label for="range" class="form-label">Range</label>
<input type="range" class="form-range" id="range" min="0" max="100">
</div>
<!-- File input -->
<div class="mb-3">
<label for="file" class="form-label">Upload file</label>
<input class="form-control" type="file" id="file">
</div>
<!-- Colour picker -->
<div class="mb-3">
<label for="colour" class="form-label">Colour</label>
<input type="color" class="form-control form-control-color"
id="colour" value="#563d7c">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
Form Layouts
<!-- Horizontal form -->
<form>
<div class="row mb-3">
<label for="inputEmail" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="inputEmail">
</div>
</div>
<div class="row mb-3">
<label for="inputPassword" class="col-sm-2 col-form-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword">
</div>
</div>
</form>
<!-- Inline form -->
<form class="row row-cols-lg-auto g-3 align-items-center">
<div class="col-12">
<input type="text" class="form-control" placeholder="Username">
</div>
<div class="col-12">
<select class="form-select">
<option selected>Choose...</option>
</select>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
<!-- Floating labels -->
<div class="form-floating mb-3">
<input type="email" class="form-control" id="floatingInput"
placeholder="name@example.com">
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<textarea class="form-control" placeholder="Comment"
id="floatingTextarea"></textarea>
<label for="floatingTextarea">Comments</label>
</div>
<!-- Input groups -->
<div class="input-group mb-3">
<span class="input-group-text">@</span>
<input type="text" class="form-control" placeholder="Username">
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Amount">
<span class="input-group-text">.00</span>
</div>
<div class="input-group">
<span class="input-group-text">With textarea</span>
<textarea class="form-control"></textarea>
</div>
<!-- Sizing -->
<input class="form-control form-control-lg" type="text" placeholder="Large">
<input class="form-control" type="text" placeholder="Default">
<input class="form-control form-control-sm" type="text" placeholder="Small">
<!-- Disabled and readonly -->
<input class="form-control" type="text" disabled>
<input class="form-control" type="text" readonly>
<input class="form-control-plaintext" type="text" readonly value="Plain text">
Form Validation
<!-- Custom validation -->
<form class="needs-validation" novalidate>
<div class="mb-3">
<label for="validationCustom01" class="form-label">First name</label>
<input type="text" class="form-control" id="validationCustom01" required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Please provide your first name.</div>
</div>
<div class="mb-3">
<label for="validationCustom02" class="form-label">Email</label>
<input type="email" class="form-control" id="validationCustom02" required>
<div class="invalid-feedback">Please provide a valid email.</div>
</div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="invalidCheck" required>
<label class="form-check-label" for="invalidCheck">
Agree to terms and conditions
</label>
<div class="invalid-feedback">You must agree before submitting.</div>
</div>
</div>
<button class="btn btn-primary" type="submit">Submit form</button>
</form>
<script>
// Custom validation script
(function () {
'use strict'
var forms = document.querySelectorAll('.needs-validation')
Array.prototype.slice.call(forms)
.forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>
<!-- Server-side validation states -->
<input type="text" class="form-control is-valid">
<div class="valid-feedback">Looks good!</div>
<input type="text" class="form-control is-invalid">
<div class="invalid-feedback">Please enter a value.</div>
<!-- Tooltips instead of feedback -->
<div class="mb-3 position-relative">
<input type="text" class="form-control is-invalid" required>
<div class="invalid-tooltip">Please fill out this field.</div>
</div>
Bootstrap Icons
Key Concepts
Bootstrap Icons is a free, high-quality, open-source icon library with over 1,800 icons designed to work seamlessly with Bootstrap components.
Installation
<!-- CDN -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.css">
<!-- npm -->
npm install bootstrap-icons
Usage Methods
<!-- Font icons (recommended) -->
<i class="bi bi-alarm"></i>
<i class="bi bi-arrow-right"></i>
<i class="bi bi-check-circle"></i>
<!-- Sizing with font utilities -->
<i class="bi bi-heart" style="font-size: 2rem;"></i>
<i class="bi bi-heart fs-1"></i>
<!-- Colouring with text utilities -->
<i class="bi bi-star-fill text-warning"></i>
<i class="bi bi-check-circle-fill text-success"></i>
<i class="bi bi-x-circle-fill text-danger"></i>
<!-- SVG sprite -->
<svg class="bi" width="32" height="32" fill="currentColor">
<use xlink:href="bootstrap-icons.svg#heart-fill"/>
</svg>
<!-- Inline SVG -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
fill="currentColor" class="bi bi-heart" viewBox="0 0 16 16">
<path d="..."/>
</svg>
Common Icons
<!-- Navigation -->
<i class="bi bi-house"></i> <!-- Home -->
<i class="bi bi-list"></i> <!-- Menu/Hamburger -->
<i class="bi bi-search"></i> <!-- Search -->
<i class="bi bi-person"></i> <!-- User -->
<i class="bi bi-gear"></i> <!-- Settings -->
<!-- Actions -->
<i class="bi bi-plus"></i> <!-- Add -->
<i class="bi bi-pencil"></i> <!-- Edit -->
<i class="bi bi-trash"></i> <!-- Delete -->
<i class="bi bi-download"></i> <!-- Download -->
<i class="bi bi-upload"></i> <!-- Upload -->
<i class="bi bi-share"></i> <!-- Share -->
<!-- Status -->
<i class="bi bi-check"></i> <!-- Success -->
<i class="bi bi-x"></i> <!-- Close/Error -->
<i class="bi bi-exclamation-triangle"></i> <!-- Warning -->
<i class="bi bi-info-circle"></i> <!-- Info -->
<!-- Social -->
<i class="bi bi-facebook"></i>
<i class="bi bi-twitter"></i>
<i class="bi bi-instagram"></i>
<i class="bi bi-linkedin"></i>
<i class="bi bi-github"></i>
<i class="bi bi-youtube"></i>
<!-- Arrows -->
<i class="bi bi-arrow-up"></i>
<i class="bi bi-arrow-down"></i>
<i class="bi bi-arrow-left"></i>
<i class="bi bi-arrow-right"></i>
<i class="bi bi-chevron-up"></i>
<i class="bi bi-chevron-down"></i>
<!-- Communication -->
<i class="bi bi-envelope"></i> <!-- Email -->
<i class="bi bi-telephone"></i> <!-- Phone -->
<i class="bi bi-chat"></i> <!-- Message -->
<i class="bi bi-bell"></i> <!-- Notification -->
Examples
<!-- Button with icon -->
<button class="btn btn-primary">
<i class="bi bi-download me-2"></i>Download
</button>
<!-- Icon-only button -->
<button class="btn btn-outline-secondary" aria-label="Edit">
<i class="bi bi-pencil"></i>
</button>
<!-- Input with icon -->
<div class="input-group">
<span class="input-group-text"><i class="bi bi-search"></i></span>
<input type="text" class="form-control" placeholder="Search...">
</div>
<!-- Social links -->
<div class="d-flex gap-3 fs-4">
<a href="#" class="text-dark"><i class="bi bi-facebook"></i></a>
<a href="#" class="text-dark"><i class="bi bi-twitter"></i></a>
<a href="#" class="text-dark"><i class="bi bi-instagram"></i></a>
</div>
<!-- Alert with icon -->
<div class="alert alert-success d-flex align-items-center" role="alert">
<i class="bi bi-check-circle-fill me-2"></i>
<div>Your changes have been saved successfully.</div>
</div>
<!-- List with icons -->
<ul class="list-unstyled">
<li class="mb-2"><i class="bi bi-check text-success me-2"></i>Feature 1</li>
<li class="mb-2"><i class="bi bi-check text-success me-2"></i>Feature 2</li>
<li class="mb-2"><i class="bi bi-x text-danger me-2"></i>Not included</li>
</ul>
Customisation
Key Concepts
Bootstrap 5 offers extensive customisation options through CSS custom properties (variables) and Sass.
CSS Custom Properties
/* Override Bootstrap variables */
:root {
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-body-font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-pill: 50rem;
}
/* Component-specific variables */
.card {
--bs-card-spacer-y: 1rem;
--bs-card-spacer-x: 1rem;
--bs-card-border-width: 1px;
--bs-card-border-radius: 0.375rem;
--bs-card-bg: #fff;
}
/* Dark mode with CSS variables */
[data-bs-theme="dark"] {
--bs-body-color: #dee2e6;
--bs-body-bg: #212529;
}
Sass Customisation
// 1. Include functions first
@import "bootstrap/scss/functions";
// 2. Override default variables
$primary: #0d6efd;
$secondary: #6c757d;
$success: #198754;
$info: #0dcaf0;
$warning: #ffc107;
$danger: #dc3545;
$light: #f8f9fa;
$dark: #212529;
// Custom colours
$custom-colours: (
"custom-colour": #ff6b6b
);
// Merge with theme colours (Bootstrap's map is $theme-colors — US spelling required)
$theme-colors: map-merge($theme-colors, $custom-colours);
// Spacing
$spacer: 1rem;
$spacers: (
0: 0,
1: $spacer * .25,
2: $spacer * .5,
3: $spacer,
4: $spacer * 1.5,
5: $spacer * 3,
);
// Grid
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 1400px
);
$container-max-widths: (
sm: 540px,
md: 720px,
lg: 960px,
xl: 1140px,
xxl: 1320px
);
// Typography
$font-family-base: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
$font-size-base: 1rem;
$line-height-base: 1.5;
// Borders
$border-radius: 0.375rem;
$border-radius-sm: 0.25rem;
$border-radius-lg: 0.5rem;
// 3. Include remainder of required Bootstrap stylesheets
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/root";
// 4. Include any optional parts as needed
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/type";
@import "bootstrap/scss/images";
@import "bootstrap/scss/containers";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/forms";
// ... add more as needed
// 5. Add custom utilities
$utilities: map-merge(
$utilities,
(
"cursor": (
property: cursor,
class: cursor,
responsive: true,
values: auto pointer grab
)
)
);
// Generate utilities
@import "bootstrap/scss/utilities/api";
Dark Mode
<!-- Enable dark mode on specific element -->
<div data-bs-theme="dark">
<!-- All Bootstrap components inside will use dark theme -->
<div class="card">
<div class="card-body">Dark themed card</div>
</div>
</div>
<!-- Toggle dark mode with JavaScript -->
<script>
function toggleDarkMode() {
const html = document.documentElement;
const currentTheme = html.getAttribute('data-bs-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
html.setAttribute('data-bs-theme', newTheme);
localStorage.setItem('theme', newTheme);
}
// Load saved theme
document.addEventListener('DOMContentLoaded', () => {
const savedTheme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-bs-theme', savedTheme);
});
</script>
Common Layout Patterns
Holy Grail Layout
<div class="d-flex flex-column min-vh-100">
<!-- Header -->
<header class="bg-dark text-white p-3">
<h1>Header</h1>
</header>
<!-- Main content with sidebars -->
<div class="container-fluid flex-grow-1">
<div class="row h-100">
<!-- Left sidebar -->
<nav class="col-md-3 col-lg-2 d-md-block bg-light sidebar">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
</ul>
</nav>
<!-- Main content -->
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<h2>Main Content</h2>
</main>
</div>
</div>
<!-- Footer -->
<footer class="bg-dark text-white p-3 mt-auto">
<p class="mb-0">Footer</p>
</footer>
</div>
Sticky Footer
<div class="d-flex flex-column min-vh-100">
<header class="bg-primary text-white p-3">Header</header>
<main class="flex-grow-1 container py-4">
Main content
</main>
<footer class="bg-dark text-white p-3 mt-auto">
Sticky footer
</footer>
</div>
Centred Content
<!-- Horizontally and vertically centred -->
<div class="d-flex align-items-center justify-content-center min-vh-100">
<div class="text-center">
<h1>Centred Content</h1>
<p>This content is centred on the page.</p>
</div>
</div>
<!-- Centred login form -->
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 col-lg-4">
<div class="card mt-5">
<div class="card-body">
<h5 class="card-title text-center">Login</h5>
<form>
<div class="mb-3">
<input type="email" class="form-control" placeholder="Email">
</div>
<div class="mb-3">
<input type="password" class="form-control" placeholder="Password">
</div>
<button type="submit" class="btn btn-primary w-100">Login</button>
</form>
</div>
</div>
</div>
</div>
</div>
Dashboard Layout
<div class="container-fluid">
<div class="row">
<!-- Sidebar -->
<nav class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse"
style="min-height: 100vh;">
<div class="position-sticky pt-3">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="#">
<i class="bi bi-house-door me-2"></i>Dashboard
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-file-earmark me-2"></i>Orders
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-cart me-2"></i>Products
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-people me-2"></i>Customers
</a>
</li>
</ul>
</div>
</nav>
<!-- Main content -->
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap
align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Dashboard</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group me-2">
<button type="button" class="btn btn-sm btn-outline-secondary">Share</button>
<button type="button" class="btn btn-sm btn-outline-secondary">Export</button>
</div>
</div>
</div>
<!-- Stats cards -->
<div class="row row-cols-1 row-cols-md-2 row-cols-xl-4 g-3 mb-4">
<div class="col">
<div class="card text-white bg-primary">
<div class="card-body">
<h5 class="card-title">Users</h5>
<p class="card-text fs-2">1,234</p>
</div>
</div>
</div>
<!-- More stat cards... -->
</div>
</main>
</div>
</div>
Feature Grid
<div class="container py-5">
<h2 class="text-center mb-5">Features</h2>
<div class="row g-4">
<div class="col-md-6 col-lg-4">
<div class="text-center">
<div class="bg-primary text-white rounded-circle d-inline-flex
align-items-center justify-content-center mb-3"
style="width: 64px; height: 64px;">
<i class="bi bi-lightning fs-4"></i>
</div>
<h4>Fast</h4>
<p class="text-muted">Lightning-fast performance for your applications.</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="text-center">
<div class="bg-success text-white rounded-circle d-inline-flex
align-items-center justify-content-center mb-3"
style="width: 64px; height: 64px;">
<i class="bi bi-shield-check fs-4"></i>
</div>
<h4>Secure</h4>
<p class="text-muted">Enterprise-grade security built in.</p>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="text-center">
<div class="bg-info text-white rounded-circle d-inline-flex
align-items-center justify-content-center mb-3"
style="width: 64px; height: 64px;">
<i class="bi bi-gear fs-4"></i>
</div>
<h4>Flexible</h4>
<p class="text-muted">Customise everything to your needs.</p>
</div>
</div>
</div>
</div>
Hero Section
<div class="bg-dark text-white">
<div class="container py-5">
<div class="row align-items-center g-5 py-5">
<div class="col-lg-6">
<h1 class="display-4 fw-bold lh-1 mb-3">
Build fast, responsive sites with Bootstrap
</h1>
<p class="lead">
Quickly design and customise responsive mobile-first sites with
Bootstrap, the world's most popular front-end open-source toolkit.
</p>
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
<button type="button" class="btn btn-primary btn-lg px-4 me-md-2">
Get Started
</button>
<button type="button" class="btn btn-outline-light btn-lg px-4">
Learn More
</button>
</div>
</div>
<div class="col-lg-6">
<img src="hero-image.svg" class="d-block mx-lg-auto img-fluid"
alt="Hero image" loading="lazy">
</div>
</div>
</div>
</div>
Quick Reference
| Category | Class/Pattern | Description |
|---|---|---|
| Container | .container |
Fixed-width responsive container |
.container-fluid |
Full-width container | |
.container-{breakpoint} |
100% until breakpoint | |
| Grid | .row |
Flex container for columns |
.col, .col-{n} |
Auto/specific width column | |
.col-{bp}-{n} |
Responsive column width | |
.g-{n}, .gx-{n}, .gy-{n} |
Gutters (all, horizontal, vertical) | |
.offset-{n} |
Column offset | |
| Display | .d-none, .d-block, .d-flex |
Display properties |
.d-{bp}-{value} |
Responsive display | |
| Flexbox | .justify-content-{value} |
Main axis alignment |
.align-items-{value} |
Cross axis alignment | |
.flex-{direction} |
Flex direction | |
.flex-wrap |
Enable wrapping | |
| Spacing | .m{side}-{size} |
Margin |
.p{side}-{size} |
Padding | |
.gap-{size} |
Gap for flex/grid | |
| Text | .text-{start|center|end} |
Text alignment |
.text-{colour} |
Text colour | |
.fs-{1-6} |
Font size | |
.fw-{bold|normal|light} |
Font weight | |
| Background | .bg-{colour} |
Background colour |
.bg-opacity-{25|50|75} |
Background opacity | |
| Border | .border, .border-{side} |
Add border |
.border-0 |
Remove border | |
.rounded, .rounded-{size} |
Border radius | |
| Sizing | .w-{25|50|75|100|auto} |
Width |
.h-{25|50|75|100|auto} |
Height | |
.min-vh-100 |
Min viewport height | |
| Position | .position-{value} |
Position type |
.top-0, .start-50, etc. |
Position values | |
.translate-middle |
Centre transform | |
| Shadow | .shadow, .shadow-{sm|lg} |
Box shadow |
| Visibility | .visible, .invisible |
Visibility |
.visually-hidden |
Screen reader only |
Common Issues and Solutions
Issue: Grid columns not aligning properly
Cause: Missing .row wrapper or incorrect nesting.
Solution:
<!-- Wrong -->
<div class="container">
<div class="col-6">Column 1</div>
<div class="col-6">Column 2</div>
</div>
<!-- Correct -->
<div class="container">
<div class="row">
<div class="col-6">Column 1</div>
<div class="col-6">Column 2</div>
</div>
</div>
Issue: JavaScript components not working
Cause: Missing Bootstrap JavaScript or jQuery (not needed in v5).
Solution:
<!-- Include Bootstrap JS before closing body tag -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
<!-- Or individual components -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.min.js"></script>
Issue: Tooltips and popovers not appearing
Cause: These components require initialisation.
Solution:
// Initialise all tooltips
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl)
})
// Initialise all popovers
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl)
})
Issue: Custom Sass variables not applying
Cause: Variables must be defined before importing Bootstrap.
Solution:
// 1. Define custom variables BEFORE importing Bootstrap
$primary: #ff6b6b;
$border-radius: 0.5rem;
// 2. Then import Bootstrap
@import "bootstrap/scss/bootstrap";
Issue: Navbar collapse not working on mobile
Cause: Missing data-bs-target or incorrect ID reference.
Solution:
<!-- Ensure IDs match -->
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNav"> <!-- Must match -->
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav"> <!-- Must match -->
<!-- Nav items -->
</div>
Issue: Form validation not triggering
Cause: Missing novalidate attribute and validation script.
Solution:
<form class="needs-validation" novalidate>
<!-- Form fields with required attribute -->
<input type="text" class="form-control" required>
<button type="submit">Submit</button>
</form>
<script>
(function () {
'use strict'
var forms = document.querySelectorAll('.needs-validation')
Array.prototype.slice.call(forms).forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>
Issue: Modal backdrop stays after closing
Cause: Multiple modals or JavaScript errors.
Solution:
// Manually remove backdrop
document.querySelectorAll('.modal-backdrop').forEach(el => el.remove());
document.body.classList.remove('modal-open');
document.body.style.overflow = '';
document.body.style.paddingRight = '';
Issue: Carousel not auto-playing
Cause: Missing data-bs-ride="carousel" attribute.
Solution:
<div id="carouselExample" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active" data-bs-interval="3000">
<!-- Content -->
</div>
</div>
</div>
Issue: Columns wrapping unexpectedly
Cause: Margins or padding adding extra width.
Solution:
<!-- Use gutters instead of margins -->
<div class="row g-3">
<div class="col-6">
<div class="p-3 bg-light">Content</div>
</div>
<div class="col-6">
<div class="p-3 bg-light">Content</div>
</div>
</div>
<!-- Or use box-sizing correctly -->
<style>
.my-column {
box-sizing: border-box;
}
</style>
Related Topics
The following cheatsheets would complement your Bootstrap 5 knowledge:
- CSS Flexbox - Deep dive into flexbox layouts that power Bootstrap's grid system
- CSS Grid - Modern CSS grid layouts for complex designs beyond Bootstrap's grid
- Sass/SCSS - Advanced styling and Bootstrap customisation with Sass
- JavaScript ES6+ - Modern JavaScript for Bootstrap component manipulation
- Web Accessibility (WCAG) - Ensure your Bootstrap sites are accessible to all users
- Tailwind CSS - Alternative utility-first CSS framework for comparison