Enabling Dark Mode: Bootstrap

Tina Huynh - Feb 28 '23 - - Dev Community

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>
Enter fullscreen mode Exit fullscreen mode

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)
        })
      })
  })
})()
Enter fullscreen mode Exit fullscreen mode

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};

Enter fullscreen mode Exit fullscreen mode

Happy coding!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .