Enable the built in dark color mode across your entire project by adding the data-bs-theme="dark"
attribute to the <html>
element. This will apply the dark color mode to all components and elements, other than those with a specific data-bs-theme
attribute applied.
<!doctype html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
</head>
<body>
<h1>Hello, world!</h1>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
</body>
</html>
To allow visitors or users to toggle color modes, you’ll need to create a toggle element to control the data-bs-theme
attribute on the root element, <html>
. We’ve built a toggler in our documentation that initially defers to a user’s current system color mode, but provides an option to override that and pick a specific color mode.
(() => {
'use strict'
const storedTheme = localStorage.getItem('theme')
const getPreferredTheme = () => {
if (storedTheme) {
return storedTheme
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
const setTheme = function (theme) {
if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-bs-theme', 'dark')
} else {
document.documentElement.setAttribute('data-bs-theme', theme)
}
}
setTheme(getPreferredTheme())
const showActiveTheme = theme => {
const activeThemeIcon = document.querySelector('.theme-icon-active use')
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
element.classList.remove('active')
})
btnToActive.classList.add('active')
activeThemeIcon.setAttribute('href', svgOfActiveBtn)
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
if (storedTheme !== 'light' || storedTheme !== 'dark') {
setTheme(getPreferredTheme())
}
})
window.addEventListener('DOMContentLoaded', () => {
showActiveTheme(getPreferredTheme())
document.querySelectorAll('[data-bs-theme-value]')
.forEach(toggle => {
toggle.addEventListener('click', () => {
const theme = toggle.getAttribute('data-bs-theme-value')
localStorage.setItem('theme', theme)
setTheme(theme)
showActiveTheme(theme)
})
})
})
})()
Dozens of root level CSS variables are repeated as overrides for dark mode. These are scoped to the color mode selector, which defaults to data-bs-theme
but can be configured to use a prefers-color-scheme media query. Use these variables as a guideline for generating your own new color modes.
--#{$prefix}body-color: #{$body-color-dark};
--#{$prefix}body-color-rgb: #{to-rgb($body-color-dark)};
--#{$prefix}body-bg: #{$body-bg-dark};
--#{$prefix}body-bg-rgb: #{to-rgb($body-bg-dark)};
--#{$prefix}emphasis-color: #{$body-emphasis-color-dark};
--#{$prefix}emphasis-color-rgb: #{to-rgb($body-emphasis-color-dark)};
--#{$prefix}secondary-color: #{$body-secondary-color-dark};
--#{$prefix}secondary-color-rgb: #{to-rgb($body-secondary-color-dark)};
--#{$prefix}secondary-bg: #{$body-secondary-bg-dark};
--#{$prefix}secondary-bg-rgb: #{to-rgb($body-secondary-bg-dark)};
--#{$prefix}tertiary-color: #{$body-tertiary-color-dark};
--#{$prefix}tertiary-color-rgb: #{to-rgb($body-tertiary-color-dark)};
--#{$prefix}tertiary-bg: #{$body-tertiary-bg-dark};
--#{$prefix}tertiary-bg-rgb: #{to-rgb($body-tertiary-bg-dark)};
--#{$prefix}emphasis-color: #{$emphasis-color-dark};
--#{$prefix}primary-text: #{$primary-text-dark};
--#{$prefix}secondary-text: #{$secondary-text-dark};
--#{$prefix}success-text: #{$success-text-dark};
--#{$prefix}info-text: #{$info-text-dark};
--#{$prefix}warning-text: #{$warning-text-dark};
--#{$prefix}danger-text: #{$danger-text-dark};
--#{$prefix}light-text: #{$light-text-dark};
--#{$prefix}dark-text: #{$dark-text-dark};
--#{$prefix}primary-bg-subtle: #{$primary-bg-subtle-dark};
--#{$prefix}secondary-bg-subtle: #{$secondary-bg-subtle-dark};
--#{$prefix}success-bg-subtle: #{$success-bg-subtle-dark};
--#{$prefix}info-bg-subtle: #{$info-bg-subtle-dark};
--#{$prefix}warning-bg-subtle: #{$warning-bg-subtle-dark};
--#{$prefix}danger-bg-subtle: #{$danger-bg-subtle-dark};
--#{$prefix}light-bg-subtle: #{$light-bg-subtle-dark};
--#{$prefix}dark-bg-subtle: #{$dark-bg-subtle-dark};
--#{$prefix}primary-border-subtle: #{$primary-border-subtle-dark};
--#{$prefix}secondary-border-subtle: #{$secondary-border-subtle-dark};
--#{$prefix}success-border-subtle: #{$success-border-subtle-dark};
--#{$prefix}info-border-subtle: #{$info-border-subtle-dark};
--#{$prefix}warning-border-subtle: #{$warning-border-subtle-dark};
--#{$prefix}danger-border-subtle: #{$danger-border-subtle-dark};
--#{$prefix}light-border-subtle: #{$light-border-subtle-dark};
--#{$prefix}dark-border-subtle: #{$dark-border-subtle-dark};
--#{$prefix}heading-color: #{$headings-color-dark};
--#{$prefix}link-color: #{$link-color-dark};
--#{$prefix}link-hover-color: #{$link-hover-color-dark};
--#{$prefix}link-color-rgb: #{to-rgb($link-color-dark)};
--#{$prefix}link-hover-color-rgb: #{to-rgb($link-hover-color-dark)};
--#{$prefix}code-color: #{$code-color-dark};
--#{$prefix}border-color: #{$border-color-dark};
--#{$prefix}border-color-translucent: #{$border-color-translucent-dark};
Happy coding!