Bootstrap Color Modes (Dark Mode)

Since Bootstrap 5.3 there is a built in dark mode. You switch it with the attribute data-bs-theme="dark" (or "light"). All components change their colors by themselves, because Bootstrap uses CSS variables for the colors.

Dark mode for the full page

<html lang="en" data-bs-theme="dark">

Dark mode for one component

You can set the attribute on any element. The element and its children get the dark colors. It is good for a dark navbar, a dark card or a dark footer on a light page.

<div class="card mb-3">
  <div class="card-body">
    <h5 class="card-title">Light card</h5>
    <p class="card-text mb-0">The page default.</p>
  </div>
</div>
<div class="card" data-bs-theme="dark">
  <div class="card-body">
    <h5 class="card-title">Dark card</h5>
    <p class="card-text mb-0">Made with data-bs-theme="dark" on the card.</p>
  </div>
</div>
Live preview

A full page in dark mode

<div class="alert alert-primary" role="alert">An alert in dark mode</div>
<button class="btn btn-primary me-1">Primary</button>
<button class="btn btn-outline-secondary me-1">Outline</button>
<div class="form-check mt-3"><input class="form-check-input" type="checkbox" id="dk" checked><label class="form-check-label" for="dk">A checkbox</label></div>
<table class="table mt-3"><thead><tr><th>#</th><th>Name</th></tr></thead><tbody><tr><td>1</td><td>Anita</td></tr></tbody></table>
Live preview

A theme switcher

To let the user choose, change the attribute on the html element with JavaScript. We test the code in real Chrome and read the background color of the page before and after:

<button class="btn btn-secondary" id="themeBtn" type="button">Switch theme</button>
Live preview

const root = document.documentElement;
const bg = () => getComputedStyle(document.body).backgroundColor;

console.log('theme now: ' + (root.getAttribute('data-bs-theme') || 'light (default)') + ', body background: ' + bg());
root.setAttribute('data-bs-theme', 'dark');
console.log('theme now: ' + root.getAttribute('data-bs-theme') + ', body background: ' + bg());
root.setAttribute('data-bs-theme', 'light');
console.log('theme now: ' + root.getAttribute('data-bs-theme') + ', body background: ' + bg());
Console output (real Chrome)

theme now: light (default), body background: rgb(255, 255, 255)
theme now: dark, body background: rgb(33, 37, 41)
theme now: light, body background: rgb(255, 255, 255)

const root = document.documentElement;

// 1. use the saved choice, or the setting of the system
const saved = localStorage.getItem('theme');
const system = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
root.setAttribute('data-bs-theme', saved || system);

// 2. the button changes it and saves the choice
document.getElementById('themeBtn').addEventListener('click', () => {
  const next = root.getAttribute('data-bs-theme') === 'dark' ? 'light' : 'dark';
  root.setAttribute('data-bs-theme', next);
  localStorage.setItem('theme', next);
});

Put the first part of this script in the head of the page, before the CSS, so the page does not flash with the wrong colors.

Write your own CSS for both modes

  • Use the CSS variables, like var(--bs-body-bg), var(--bs-body-color) and var(--bs-border-color), in your own CSS. They change with the mode.
  • Prefer .bg-body, .bg-body-tertiary, .text-body, .text-body-secondary and the “subtle” and “emphasis” colors.
  • Avoid .bg-white, .bg-light and .text-dark for general parts, because they stay the same in dark mode.
.my-box {
  background-color: var(--bs-tertiary-bg);
  color: var(--bs-body-color);
  border: 1px solid var(--bs-border-color);
}

Old classes

The old .navbar-dark, .carousel-dark and .dropdown-menu-dark still work, but they are deprecated. Use data-bs-theme="dark" on those components.

Note: Test your page in both modes, and check the contrast of your own colors. Next: Bootstrap Icons.

Congratulations! Chapter Finished. Learn more about the similar topics:
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.