Bootstrap Dark Mode Toggle

This code switches the page between light and dark mode with data-bs-theme, uses the system setting at the first visit, and remembers the choice of the user.

HTML

<nav class="navbar bg-body-tertiary border-bottom">
  <div class="container">
    <span class="navbar-brand">My site</span>
    <button class="btn btn-outline-secondary" id="themeToggle" type="button">
      <span id="themeLabel">Dark mode</span>
    </button>
  </div>
</nav>
<p class="mt-3">Some text on the page. The colors change with the mode.</p>
Live preview

JavaScript

const root = document.documentElement;
const button = document.getElementById('themeToggle');
const label = document.getElementById('themeLabel');

function applyTheme(theme) {
  root.setAttribute('data-bs-theme', theme);
  label.textContent = theme === 'dark' ? 'Light mode' : 'Dark mode';
}

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

// 2. click: change and save
button.addEventListener('click', () => {
  const next = root.getAttribute('data-bs-theme') === 'dark' ? 'light' : 'dark';
  applyTheme(next);
  localStorage.setItem('theme', next);
});

Test of the same logic in real Chrome (without the saved value, because the preview is sandboxed):

const root = document.documentElement;
const button = document.getElementById('themeToggle');
const label = document.getElementById('themeLabel');
function applyTheme(theme) {
  root.setAttribute('data-bs-theme', theme);
  label.textContent = theme === 'dark' ? 'Light mode' : 'Dark mode';
}
button.addEventListener('click', () => {
  const next = root.getAttribute('data-bs-theme') === 'dark' ? 'light' : 'dark';
  applyTheme(next);
});
applyTheme('light');
const bg = () => getComputedStyle(document.body).backgroundColor;
console.log('light: label = "' + label.textContent + '", background = ' + bg());
button.click();
console.log('after click: theme = ' + root.getAttribute('data-bs-theme') + ', label = "' + label.textContent + '", background = ' + bg());
button.click();
console.log('after 2nd click: theme = ' + root.getAttribute('data-bs-theme') + ', label = "' + label.textContent + '", background = ' + bg());
Console output (real Chrome)

light: label = "Dark mode", background = rgb(255, 255, 255)
after click: theme = dark, label = "Light mode", background = rgb(33, 37, 41)
after 2nd click: theme = light, label = "Dark mode", background = rgb(255, 255, 255)

How it works

  • Bootstrap 5.3 reads data-bs-theme on the html element and changes all its CSS variables.
  • prefers-color-scheme is the system setting of the user, used when nothing is saved.
  • Put the first part of the script in the head, before the CSS, to avoid a flash of the wrong colors.
Note: In your own CSS, use the variables like var(--bs-body-bg) so your parts also change. See Color Modes.

Learn more about the similar topics:
Tutorials
No Content Found.
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.