Dark Mode Support

Created on 29 August 2023, 10 months ago
Updated 26 September 2023, 9 months ago

Just reading up on Dark mode and it seems to to be supported in Bootstrap 5.3 or later with the choice of either manual selection on the root element or components by default using a data attribute css selector.

e.g.

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

or at a component level:

<div class="dropdown" data-bs-theme="light">

by default this will use data attributes to target an element with scss.

$color-mode-type: data;

@include color-mode(dark) {
  .element {
    color: var(--bs-primary-text-emphasis);
    background-color: var(--bs-primary-bg-subtle);
  }
}

This compiles to css like:

[data-bs-theme=dark] .element {
  color: var(--bs-primary-text-emphasis);
  background-color: var(--bs-primary-bg-subtle);
}

However this can be switched to use media queries with the use of the $color-mode-type scss variable which by default is set to 'data'

e.g.

$color-mode-type: media-query;

@include color-mode(dark) {
  .element {
    color: var(--bs-primary-text-emphasis);
    background-color: var(--bs-primary-bg-subtle);
  }
}

outputs

@media (prefers-color-scheme: dark) {
  .element {
    color: var(--bs-primary-text-emphasis);
    background-color: var(--bs-primary-bg-subtle);
  }
}

This seems quite useful as we can then use media queries to automatically switch a theme from light or dark mode based on a users os preference.

see https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-sc...

So can we simply add this variable in some root stylesheet or similar and also add a stylesheet that can be used to customise or set some useful defaults?

Structure for that could be something like this:

:root,
[data-bs-theme="light"] {
   // Note: Custom variable values only support SassScript inside `#{}`.

   // Colors
   //
   // Generate palettes for full colors, grays, and theme colors.
   --#{$prefix}navbar-brand-color: #{$gray-800};
 
}

@if $enable-dark-mode {
   @include color-mode(dark, true) {
       color-scheme: dark;
//...
   }
}

https://getbootstrap.com/docs/5.3/customize/color-modes/#dark-mode

Feature request
Status

Active

Version

5.5

Component

Code

Created by

🇬🇧United Kingdom 2dareis2do

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @2dareis2do
  • I'm working on implementing color modes with a Barrio Bootstrap SASS sub-theme, and so far I've been able to implement a Dark, Light, and Blue mode with a few changes to the default sub-theme created by the sub-theme script.

    I started by using the current 5.0.6 Bootstrap 5 - SASS starter kit script, following the installation guidance from the Drupal Bootstrap Docs .

    With the current Drupal 10 I'm using this default sub-theme had an issue with the default bootstrap and popper libraries it setup, which prevented dropdown buttons from working properly. To fix this I edited the `gulpfile.js`, in the sub-theme, to use the `bootstrap.bundle.min.js` which integrates popper, instead of the default, separate, 'bootstrap.min.js` & `popper.min.js` libraries. Using the integrated bootstrap bundle solved whatever conflict there was in the default arrangement. NOTE: I included the `bootstrap.bundle.min.js.map` file as well to clear up a warning that appears in the browser's web inspector without it.

    What I changed in the `gulpfile.js` in the following places:

    `const paths = {}`

    const paths = {
      scss: {
        src: './scss/style.scss',
        dest: './css',
        watch: './scss/**/*.scss',
        bootstrap: './node_modules/bootstrap/scss/bootstrap.scss',
      },
      js: {
        bootstrap_bundle: './node_modules/bootstrap/dist/js/bootstrap.bundle.min.js',
        bootstrap_bundle_map: './node_modules/bootstrap/dist/js/bootstrap.bundle.min.js.map',
        // bootstrap: './node_modules/bootstrap/dist/js/bootstrap.min.js',
        // popper: './node_modules/@popperjs/core/dist/umd/popper.min.js',
        barrio: '../../contrib/bootstrap_barrio/js/barrio.js',
        dest: './js'
      }
    }

    `function js () {}`

    // Move the javascript files into our js folder
    function js () {
      // return gulp.src([paths.js.bootstrap, paths.js.popper, paths.js.barrio])
      return gulp.src([paths.js.bootstrap_bundle, paths.js.bootstrap_bundle_map, paths.js.barrio])
        .pipe(gulp.dest(paths.js.dest))
        .pipe(browserSync.stream())
    }

    I could now delete the old `popper.min.js` and `bootstrap.min.js` files in the sub-theme `js` directory as they are no longer necessary.

    Next, following the guidance on the Bootstrap 5.3 Color-Modes page, I took a copy of the toggler javascript found there, and put it into a new file I created in the sub-theme's `js` directory, called `color-modes.js`.

    Next, I updated my bootstrap sub-theme's libraries file `boot_test.libraries.yml` to reference the bootstrap bundle library I substituted for the separate bootstrap & popper libraries, as well as the new `color-modes.js` file, resulting in:

    global-styling:
      version: VERSION
      js: 
        js/color-modes.js: {}
        js/bootstrap.bundle.min.js: {minified: true, weight: -47}
        js/barrio.js: {}
        js/custom.js: {}
      css:
        component:
          css/style.css: {}
      dependencies:
        - core/jquery
        - core/drupal

    In order to add a 3rd theme to the built in 'light' and 'dark' themes already included with bootstrap 5.3, I now created a new `themes.scss` file in the sub-theme `scss` directory in which I included all the CSS variables found in the `node_modules/bootstrap/dist/css/bootstrap-utilities.css` file for the `[data-bs-theme=dark] {}` block, in a new delcaration for `[data-bs-theme=blue] {}`.

    `themes.scss`

    [data-bs-theme="blue"] {
      color-scheme: 'blue';
      --bs-body-color: #10edfd;
      --bs-body-color-rgb: 16, 237, 253;
      --bs-body-bg: #8e40d8;
      --bs-body-bg-rgb: 142, 64, 216;
      --bs-emphasis-color: #fff;
      --bs-emphasis-color-rgb: 255, 255, 255;
      --bs-secondary-color: rgba(222, 226, 230, 0.75);
      --bs-secondary-color-rgb: 222, 226, 230;
      --bs-secondary-bg: #343a40;
      --bs-secondary-bg-rgb: 52, 58, 64;
      --bs-tertiary-color: rgba(222, 226, 230, 0.5);
      --bs-tertiary-color-rgb: 222, 226, 230;
      --bs-tertiary-bg: #2b3035;
      --bs-tertiary-bg-rgb: 43, 48, 53;
      --bs-primary-text-emphasis: #6ea8fe;
      --bs-secondary-text-emphasis: #a7acb1;
      --bs-success-text-emphasis: #75b798;
      --bs-info-text-emphasis: #6edff6;
      --bs-warning-text-emphasis: #ffda6a;
      --bs-danger-text-emphasis: #ea868f;
      --bs-light-text-emphasis: #f8f9fa;
      --bs-dark-text-emphasis: #dee2e6;
      --bs-primary-bg-subtle: #031633;
      --bs-secondary-bg-subtle: #161719;
      --bs-success-bg-subtle: #051b11;
      --bs-info-bg-subtle: #032830;
      --bs-warning-bg-subtle: #332701;
      --bs-danger-bg-subtle: #2c0b0e;
      --bs-light-bg-subtle: #343a40;
      --bs-dark-bg-subtle: #1a1d20;
      --bs-primary-border-subtle: #084298;
      --bs-secondary-border-subtle: #41464b;
      --bs-success-border-subtle: #0f5132;
      --bs-info-border-subtle: #087990;
      --bs-warning-border-subtle: #997404;
      --bs-danger-border-subtle: #842029;
      --bs-light-border-subtle: #495057;
      --bs-dark-border-subtle: #343a40;
      --bs-heading-color: inherit;
      --bs-link-color: #6ea8fe;
      --bs-link-hover-color: #8bb9fe;
      --bs-link-color-rgb: 110, 168, 254;
      --bs-link-hover-color-rgb: 139, 185, 254;
      --bs-code-color: #e685b5;
      --bs-border-color: #495057;
      --bs-border-color-translucent: rgba(255, 255, 255, 0.15);
      --bs-form-valid-color: #75b798;
      --bs-form-valid-border-color: #75b798;
      --bs-form-invalid-color: #ea868f;
      --bs-form-invalid-border-color: #ea868f;
    }

    After creating a `blue` theme scss file, I added this file to the list of imports in the `import.scss` file so it will be compiled by gulp.

    `import.scss`

    /* IMPORTS */
    
    //@import url(font-awesome.min.css);
    // variables
    @import "variables";
    // typography
    @import "typography";
    //bootstrap
    @import "bootstrap";
    //material design bootstrap
    //@import "../node_modules/mdbootstrap/scss/mdb-free.scss";
    // mixins
    @import "mixins";
    // barrio
    @import "barrio";
    // color pallette themes
    @import "themes";

    Finally, I edited the sub-theme's original `scss/style.scss` file to comment out all the styling that is in there by default, except the `@import "import"` at the top. If this is not done, these styles will override the color-theme styles.

    To test the color mode toggling, I took a copy of the Drupal Barrio Bootstrap `page.html.twig` template, added it to my sub-theme's `templates` folder and then add the following toggle element code just after {{ page.top_header }}, near line 90.

    {# Beginning of theme mode selector #}
        <div class="d-flex align-items-center gap-3">
          <div class="d-flex align-items-center dropdown color-modes">
            <button class="btn btn-link px-0 text-decoration-none dropdown-toggle d-flex align-items-center"
                    id="bd-theme"
                    type="button"
                    aria-expanded="false"
                    data-bs-toggle="dropdown"
                    data-bs-display="static">
              <svg class="bi my-1 me-2 theme-icon-active"><use href="#circle-half"></use></svg>
              <span class="ms-2" id="bd-theme-text">Toggle theme</span>
            </button>
            <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="bd-theme" style="--bs-dropdown-min-width: 8rem;">
              <li>
                <button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="blue">
                  {# <svg class="bi me-2 opacity-50 theme-icon"><use href="#sun-fill"></use></svg> #}
                  blue
                  <svg class="bi ms-auto d-none"><use href="#check2"></use></svg>
                </button>
              </li>
              <li>
                <button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="light">
                  {# <svg class="bi me-2 opacity-50 theme-icon"><use href="#sun-fill"></use></svg> #}
                  Light
                  <svg class="bi ms-auto d-none"><use href="#check2"></use></svg>
                </button>
              </li>
              <li>
                <button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="dark">
                  {# <svg class="bi me-2 opacity-50 theme-icon"><use href="#moon-stars-fill"></use></svg> #}
                  Dark
                  <svg class="bi ms-auto d-none"><use href="#check2"></use></svg>
                </button>
              </li>
              <li>
                <button type="button" class="dropdown-item d-flex align-items-center active" data-bs-theme-value="auto">
                  {# <svg class="bi me-2 opacity-50 theme-icon"><use href="#circle-half"></use></svg> #}
                  Auto
                  <svg class="bi ms-auto d-none"><use href="#check2"></use></svg>
                </button>
              </li>
            </ul>
          </div>
          <a href="https://github.com/twbs/examples/tree/main/color-modes/" target="_blank" rel="noopener" class="text-decoration-none">View on GitHub</a>
        </div>
        {# ------ END of Theme Mode Selector #}

    Now everything is ready for color mode switching via this selector placed into the top_header. Make sure to change some colors inside the `themes.scss` for the `blue` mode so you can distinguish it from the `dark` settings that it was copied from.
    From the sub-theme directory, open a line command window and run `gulp`, then go to your site homepage and refresh all the caches.
    There should now be a selector in the Top Header called `Toggle theme`. Selecting 'blue', 'light', or 'dark' should update the theme colors to many of the elements on the page. Selecting `auto` should use either `light` or `dark` depending on your operating system settings. Note that Barrio variables defined in the sub-theme's `variables.scss` file will not be affected by this, so page elements styled by these Barrio variables will not change according to the selected theme.

    I have no idea if this is the best way to setup color modes, but thought I would share how I was able to get color modes partially implemented with the existing Barrio Bootstrap SASS sub-theme, and hopefully it will be useful to others also looking to integrate color modes.

  • 🇬🇧United Kingdom 2dareis2do

    Hi @mbaycura

    Thanks for sharing.

    It interesting what you are saying about setting up a Dark, Light, and Blue theme. However this issue is specifically about supporting dark mode.

    see

    https://getbootstrap.com/docs/5.3/customize/color-modes/#dark-mode

    Why setting up colour modes is also interesting,
    https://getbootstrap.com/docs/5.3/customize/color-modes/#custom-color-modes

    While the primary use case for color modes is light and dark mode, custom color modes are also possible. Create your own data-bs-theme selector with a custom value as the name of your color mode, then modify our Sass and CSS variables as needed.

    One delta here is that I am not sure you can use media queries to switch the color mode?

    With the current Drupal 10 I'm using this default sub-theme had an issue with the default bootstrap and popper libraries it setup, which prevented dropdown buttons from working properly

    Not sure if there is an issue for this, but again, if not perhaps you should raise one?

    Afaik there is already some support for colour modes from the barrio theme ui, that even gives you the option to over-ride these values. e.g.

    in web/themes/contrib/bootstrap_barrio/bootstrap_barrio.theme

    we have the following array of styles defined

     $styles = [
          "--bs-primary:$pc;",
          "--bb-primary-dark:$pcd;",
          "--bb-primary-text:$pct;",
          "--bs-primary-rgb:$pcrgb;",
          "--bs-secondary:$sc;",
          "--bb-secondary-dark:$scd;",
          "--bs-secondary-rgb:$scrgb;",
          "--bs-link-color:$pc;",
          "--bs-link-hover-color:$pcd;",
          "--bs-body-color:$color;",
          "--bs-body-bg:$bg;",
          "--bb-h1-color:$h1;",
          "--bb-h2-color:$h2;",
          "--bb-h3-color:$h3;",
        ];

    In bootstrap its a little different. We have colours defined in variables.scss e.g.

    // scss-docs-start color-variables
    $blue:    #0d6efd !default;
    $indigo:  #6610f2 !default;
    $purple:  #6f42c1 !default;
    $pink:    #d63384 !default;
    $red:     #dc3545 !default;
    $orange:  #fd7e14 !default;
    $yellow:  #ffc107 !default;
    $green:   #198754 !default;
    $teal:    #20c997 !default;
    $cyan:    #0dcaf0 !default;
    // scss-docs-end color-variables
    
    // scss-docs-start colors-map
    $colors: (
      "blue":       $blue,
      "indigo":     $indigo,
      "purple":     $purple,
      "pink":       $pink,
      "red":        $red,
      "orange":     $orange,
      "yellow":     $yellow,
      "green":      $green,
      "teal":       $teal,
      "cyan":       $cyan,
      "black":      $black,
      "white":      $white,
      "gray":       $gray-600,
      "gray-dark":  $gray-800
    ) !default;

    and stuff like this

    $body-color:                $gray-900 !default;
    $body-bg:                   $white !default;
    
    $body-secondary-color:      rgba($body-color, .75) !default;
    $body-secondary-bg:         $gray-200 !default;
    
    $body-tertiary-color:       rgba($body-color, .5) !default;
    $body-tertiary-bg:          $gray-100 !default;
    
    $body-emphasis-color:       $black !default;

    and then in variables-dark we have these overrides and variations e.g.:

    $body-color-dark:                   $gray-300 !default;
    $body-bg-dark:                      $gray-900 !default;
    $body-secondary-color-dark:         rgba($body-color-dark, .75) !default;
    $body-secondary-bg-dark:            $gray-800 !default;
    $body-tertiary-color-dark:          rgba($body-color-dark, .5) !default;
    $body-tertiary-bg-dark:             mix($gray-800, $gray-900, 50%) !default;
    $body-emphasis-color-dark:          $white !default;
    $border-color-dark:                 $gray-700 !default;
    $border-color-translucent-dark:     rgba($white, .15) !default;
    $headings-color-dark:               inherit !default;
    $link-color-dark:                   tint-color($primary, 40%) !default;
    $link-hover-color-dark:             shift-color($link-color-dark, -$link-shade-percentage) !default;
    $code-color-dark:                   tint-color($code-color, 40%) !default;
    

    In root.scss we then have scss like so:

      --#{$prefix}body-color: #{$body-color};
      --#{$prefix}body-color-rgb: #{to-rgb($body-color)};
      --#{$prefix}body-bg: #{$body-bg};
      --#{$prefix}body-bg-rgb: #{to-rgb($body-bg)};

    e.g. https://github.com/twbs/bootstrap/blob/413894d4691b5ebb1377fcf5ab8fd3bba...

    In the scss you have stuff like this:

    @if $enable-dark-mode {
       @include color-mode(dark) {
          .navbar-toggler-icon {
             --#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
          }
       }
    }

    which outputs like

  • 🇬🇧United Kingdom 2dareis2do

    I think a good place to start wigth this would be to add the following scss files:

    _root - required for dark mode support
    _variables (exists but delta with bootstrap)
    _variables dark - required to define _variables_dark

  • I've finished building a theme mode toggler control, that can enable the integration of light & dark themes on a Barrio Bootstrap 5 theme, or theme built using the Barrio Bootstrap SASS Starter Kit.

    Though this may not be the 'out of box' integration you are looking for, it will implement light & dark modes on existing Barrio themes.
    Bootstrap Theme Toggler module
    module's documentation

  • 🇵🇪Peru hatuhay Lima

    Latest DEV version integrates light and dark Bootstrap modes.
    The switcher does a perfect match.
    From Barrio perspective there is a little more work pending taking dark mode variables to the administration.

  • 🇬🇧United Kingdom 2dareis2do

    Thanks for sharing @mbaycura

Production build 0.69.0 2024