I've shipped a lot of Bootstrap projects over the years. Here are the practices that actually matter — things that have saved me time, prevented bugs and kept codebases maintainable.

1. Always Use the Bundle JS

This is so basic but I see it wrong constantly.

<!-- ❌ Wrong — dropdowns and collapse won't work -->
<script src="bootstrap.min.js"></script>

<!-- ✅ Correct — includes Popper.js -->
<script src="bootstrap.bundle.min.js"></script>

bootstrap.bundle.min.js bundles Popper.js. Without it, dropdowns, tooltips, popovers and the navbar collapse won't function.

2. Include the Viewport Meta Tag

<!-- ❌ Missing — mobile layout breaks completely -->
<head>
  <link href="bootstrap.min.css" rel="stylesheet">
</head>

<!-- ✅ Always include this -->
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="bootstrap.min.css" rel="stylesheet">
</head>

Bootstrap is mobile-first. Without the viewport tag, your responsive grid does nothing on mobile.

3. Use Sass Variables, Not !important

/* ❌ Fighting Bootstrap with !important */
.btn-primary {
  background-color: #fd4766 !important;
  border-color: #fd4766 !important;
}

/* ✅ Override before Bootstrap compiles */
$primary: #fd4766;
@import "bootstrap/scss/bootstrap";

Override Sass variables once and Bootstrap applies your colors consistently everywhere — buttons, badges, focus rings, active states. One line instead of hunting down every component.

4. Don't Nest Containers

<!-- ❌ Double container — adds double padding -->
<div class="container">
  <div class="container">
    <p>Content</p>
  </div>
</div>

<!-- ✅ One container per section -->
<div class="container">
  <p>Content</p>
</div>

Every container adds horizontal padding. Nesting them doubles it and limits your content width unnecessarily.

5. Use Semantic HTML, Not Just Divs

<!-- ❌ Divs for everything -->
<div class="nav">
  <div class="nav-item">
    <div class="nav-link">Home</div>
  </div>
</div>

<!-- ✅ Proper semantic elements -->
<nav class="navbar">
  <ul class="navbar-nav">
    <li class="nav-item">
      <a class="nav-link" href="/">Home</a>
    </li>
  </ul>
</nav>

Bootstrap's classes are designed for semantic HTML. Using the right elements improves accessibility, SEO and the behavior of assistive technologies.

6. Lazy Load Images

<!-- ❌ All images load immediately -->
<img src="product.jpg" class="img-fluid">

<!-- ✅ Native lazy loading -->
<img src="product.jpg" class="img-fluid" loading="lazy" alt="Product name">

Bootstrap 5 removed lozad.js support — use the native loading="lazy" attribute. Also always include alt text.

7. Initialize JS Components Once

/* ❌ Creates a new instance every click — memory leak */
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
  el.addEventListener('click', () => new bootstrap.Tooltip(el))
})

/* ✅ Initialize once on page load */
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
  new bootstrap.Tooltip(el)
})

Bootstrap's tooltip, popover and modal instances should be created once. If you need to interact with them later, use getInstance.

8. Use Gap Utilities Instead of Margin Hacks

<!-- ❌ Manual margin on every child -->
<div class="d-flex">
  <button class="btn btn-primary me-2">One</button>
  <button class="btn btn-secondary me-2">Two</button>
  <button class="btn btn-success">Three</button>
</div>

<!-- ✅ Gap on the parent -->
<div class="d-flex gap-2">
  <button class="btn btn-primary">One</button>
  <button class="btn btn-secondary">Two</button>
  <button class="btn btn-success">Three</button>
</div>

gap-2 on a flex container spaces all children evenly without you managing individual margins. Works on grid containers too.

9. Use Component States Correctly

<!-- ❌ Hardcoded active class, never updates -->
<a class="nav-link active" href="/">Home</a>
<a class="nav-link active" href="/about">About</a>

<!-- ✅ Only current page gets active -->
<a class="nav-link active" aria-current="page" href="/">Home</a>
<a class="nav-link" href="/about">About</a>

active should only be on the current page/item. Include aria-current="page" for accessibility. In frameworks like Angular and React, derive the active state from the router instead of hardcoding it.

10. Use Custom Properties for Theming

Bootstrap 5.2+ ships with CSS custom properties on every component. Use them instead of hardcoding colors:

/* ❌ Hardcoded color */
.my-card { background-color: #ffffff; border-color: #dee2e6; }

/* ✅ Uses Bootstrap's theme variables — switches with dark mode */
.my-card {
  background-color: var(--bs-body-bg);
  border-color: var(--bs-border-color);
}

This matters enormously if you implement dark mode. Hardcoded colors break in dark mode. CSS variables switch automatically.

Frequently Asked Questions

CDN for simple projects — jsDelivr is reliable and fast. Self-host for production apps where you want full control, offline capability or have already customized Bootstrap with Sass. If you're using Vite or Webpack, npm install and bundle it yourself.
No. Bootstrap 5 utility classes are designed to be composed. Using d-flex, gap-3, p-4 etc directly in HTML is the intended usage pattern. The only real downside is HTML verbosity — if you find yourself repeating the same 8 utility classes on every card, extract them into a component.
Load your custom CSS after Bootstrap. Use more specific selectors when overriding: .my-nav .nav-link instead of just .nav-link. For large projects, use a CSS namespace or Sass to scope your overrides. Avoid !important — it's a sign of a specificity problem.

Need a Full Bootstrap 5 Admin Dashboard?

Get a complete Angular 21 + Bootstrap 5 dashboard with 50+ components — built by the same team behind BootstrapPlanet.

Browse Templates →

Use code FIRST30 for 30% off your first purchase.

Related Components