跳至主要内容 跳至文档导航

颜色模式

从 v5.3.0 开始,Bootstrap 现在支持颜色模式或主题。探索我们的默认浅色模式和新的深色模式,或使用我们的样式作为模板创建您自己的模式。

深色模式

Bootstrap 现在支持颜色模式,从深色模式开始! 在 v5.3.0 中,您可以实现自己的颜色模式切换器(请参阅下面的 Bootstrap 文档中的示例)并根据需要应用不同的颜色模式。我们支持浅色模式(默认)和现在的深色模式。由于 data-bs-theme 属性,可以在<html>元素或特定组件和元素上全局切换颜色模式。

或者,您也可以切换到媒体查询实现,这要归功于我们的颜色模式 mixin — 有关详细信息,请参阅 用法部分。不过请注意 - 这消除了您按组件更改主题的能力,如下所示。

示例

例如,要更改下拉菜单的颜色模式,请将 data-bs-theme="light"data-bs-theme="dark"添加到父.dropdown中。现在,无论全局颜色模式如何,这些下拉列表都将以指定的主题值显示。

html
<div class="dropdown" data-bs-theme="light">
  <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButtonLight" data-bs-toggle="dropdown" aria-expanded="false">
    Default dropdown
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButtonLight">
    <li><a class="dropdown-item active" href="#">Action</a></li>
    <li><a class="dropdown-item" href="#">Action</a></li>
    <li><a class="dropdown-item" href="#">Another action</a></li>
    <li><a class="dropdown-item" href="#">Something else here</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">Separated link</a></li>
  </ul>
</div>

<div class="dropdown" data-bs-theme="dark">
  <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButtonDark" data-bs-toggle="dropdown" aria-expanded="false">
    Dark dropdown
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButtonDark">
    <li><a class="dropdown-item active" href="#">Action</a></li>
    <li><a class="dropdown-item" href="#">Action</a></li>
    <li><a class="dropdown-item" href="#">Another action</a></li>
    <li><a class="dropdown-item" href="#">Something else here</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">Separated link</a></li>
  </ul>
</div>

工作原理

  • 如上所示,颜色模式样式由 data-bs-theme 属性控制。此属性可以应用于 <html>元素,也可以应用于任何其他元素或Bootstrap组件。如果应用于 <html>元素,它将应用于所有内容。如果应用于组件或元素,则其范围将限定为该特定组件或元素。

  • 对于您希望支持的每种颜色模式,您需要为共享的全局 CSS 变量添加新的覆盖。我们已经在暗模式的_root.scss样式表中执行此操作,浅色模式是默认值。在编写特定于颜色模式的样式时,请使用 mixin:

    // Color mode variables in _root.scss
    @include color-mode(dark) {
      // CSS variable overrides here...
    }
    
  • 我们使用自定义的_variables-dark.scss来支持暗模式的共享全局CSS变量覆盖。此文件对于您自己的自定义颜色模式不是必需的,但出于两个原因,我们的深色模式需要此文件。首先,最好有一个位置来重置全局颜色。其次,对于嵌入在CSS中的手风琴、表单组件等背景图像,必须覆盖一些Sass变量。

用法

启用深色模式

通过将data-bs-theme="dark"属性添加到<html>元素,在整个项目中启用内置的深色模式。这会将深色模式应用于所有组件和元素,但应用了特定 data-bs-theme 属性的组件和元素除外。基于 快速入门模板

<!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-alpha2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
  </head>
  <body>
    <h1>Hello, world!</h1>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/js/bootstrap.bundle.min.js" integrity="sha384-qKXV1j0HvMUeCBQ+QVp7JcfGl760yU08IQ+GpUo5hlbpg51QRiuqHAJz8+BrxE/N" crossorigin="anonymous"></script>
  </body>
</html>

Bootstrap 尚未附带内置的颜色模式选择器,但如果您愿意,可以使用我们自己文档中的颜色模式选择器。在 JavaScript 部分了解更多信息。

与Sass一起建造

我们新的暗模式选项可供 Bootstrap 的所有用户使用,但它通过数据属性而不是媒体查询进行控制,并且不会自动切换项目的颜色模式。您可以通过 Sass 将$enable-dark-mode更改为 false来完全禁用我们的暗模式。

我们使用自定义的 Sass mixin,color-mode(),来帮助您控制 how 颜色模式的应用。默认情况下,我们使用 data属性方法,允许您创建更加用户友好的体验,您的访问者可以选择使用自动深色模式或控制他们的偏好(就像我们自己的文档一样)。这也是一种简单且可扩展的方法,可以添加不同的主题和更多自定义颜色模式,超越浅色和深色。

如果您想使用媒体查询并且仅使颜色模式自动,您可以通过 Sass 变量更改 mixin 的默认类型。请考虑以下代码片段及其编译的 CSS 输出。

$color-mode-type: data;

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

输出到:

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

当设置为 media-query时:

$color-mode-type: media-query;

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

输出到:

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

自定义颜色模式

虽然颜色模式的主要用例是浅色和深色模式,但也可以自定义颜色模式。使用自定义值作为颜色模式的名称创建您自己的 data-bs-theme选择器,然后根据需要修改我们的 Sass 和 CSS 变量。我们选择创建一个单独的 _variables-dark.scss样式表来容纳 Bootstrap 的暗模式特定 Sass 变量,但这对您来说不是必需的。

例如,您可以使用选择器 data-bs-theme="blue"创建一个”蓝色主题”。在自定义 Sass 或 CSS 文件中,添加新的选择器并根据需要覆盖任何全局或组件 CSS 变量。如果你使用的是 Sass,你也可以在 CSS 变量覆盖中使用 Sass 的函数。

[data-bs-theme="blue"] {
  --bs-body-color: var(--bs-white);
  --bs-body-color-rgb: #{to-rgb($white)};
  --bs-body-bg: var(--bs-blue);
  --bs-body-bg-rgb: #{to-rgb($blue)};
  --bs-tertiary-bg: #{$blue-600};

  .dropdown-menu {
    --bs-dropdown-bg: #{mix($blue-500, $blue-600)};
    --bs-dropdown-link-active-bg: #{$blue-700};
  }

  .btn-secondary {
    --bs-btn-bg: #{mix($gray-600, $blue-400, .5)};
    --bs-btn-border-color: #{rgba($white, .25)};
    --bs-btn-hover-bg: #{darken(mix($gray-600, $blue-400, .5), 5%)};
    --bs-btn-hover-border-color: #{rgba($white, .25)};
    --bs-btn-active-bg: #{darken(mix($gray-600, $blue-400, .5), 10%)};
    --bs-btn-active-border-color: #{rgba($white, .5)};
    --bs-btn-focus-border-color: #{rgba($white, .5)};
    --bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(255, 255, 255, .2);
  }
}
Example blue theme

Some paragraph text to show how the blue theme might look with written copy.


<div data-bs-theme="blue">
  ...
</div>

JavaScript

要允许访问者或用户切换颜色模式,您需要创建一个切换元素来控制根元素<html>上的 data-bs-theme属性。我们在文档中构建了一个切换器,该切换器最初遵循用户的当前系统颜色模式,但提供了一个选项来覆盖该模式并选择特定的颜色模式。

以下是支持它的JavaScript。请随意检查我们自己的文档导航栏,看看如何使用我们自己组件中的 HTML 和 CSS 实现它。请注意,如果您决定对颜色模式使用媒体查询,则可能需要修改或删除您的 JavaScript(如果您更喜欢隐式控件)。

/*!
 * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
 * Copyright 2011-2023 The Bootstrap Authors
 * Licensed under the Creative Commons Attribution 3.0 Unported License.
 */

(() => {
  '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, focus = false) => {
    const themeSwitcher = document.querySelector('#bd-theme')

    if (!themeSwitcher) {
      return
    }

    const themeSwitcherText = document.querySelector('#bd-theme-text')
    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')
      element.setAttribute('aria-pressed', 'false')
    })

    btnToActive.classList.add('active')
    btnToActive.setAttribute('aria-pressed', 'true')
    activeThemeIcon.setAttribute('href', svgOfActiveBtn)
    const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
    themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)

    if (focus) {
      themeSwitcher.focus()
    }
  }

  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, true)
        })
      })
  })
})()

CSS

变量

数十个根级 CSS 变量被重复作为暗模式的覆盖。这些范围限定为颜色模式选择器,该选择器默认为data-bs-theme,但可以配置以使用prefers-color-scheme媒体查询。使用这些变量作为生成自己的新颜色模式的指南。

--#{$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)};

@each $color, $value in $theme-colors-text-dark {
  --#{$prefix}#{$color}-text-emphasis: #{$value};
}

@each $color, $value in $theme-colors-bg-subtle-dark {
  --#{$prefix}#{$color}-bg-subtle: #{$value};
}

@each $color, $value in $theme-colors-border-subtle-dark {
  --#{$prefix}#{$color}-border-subtle: #{$value};
}

@if $headings-color-dark != null {
  --#{$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};

--#{$prefix}form-valid-color: #{$form-valid-color-dark};
--#{$prefix}form-valid-border-color: #{$form-valid-border-color-dark};
--#{$prefix}form-invalid-color: #{$form-invalid-color-dark};
--#{$prefix}form-invalid-border-color: #{$form-invalid-border-color-dark};

Sass 变量

深色模式的 CSS 变量部分由 _variables-dark.scss 中特定于深色模式的 Sass 变量生成。这还包括一些自定义覆盖,用于更改整个组件中使用的嵌入式 SVG 的颜色。

// scss-docs-start theme-text-dark-variables
$primary-text-emphasis-dark:        tint-color($primary, 40%);
$secondary-text-emphasis-dark:      tint-color($secondary, 40%);
$success-text-emphasis-dark:        tint-color($success, 40%);
$info-text-emphasis-dark:           tint-color($info, 40%);
$warning-text-emphasis-dark:        tint-color($warning, 40%);
$danger-text-emphasis-dark:         tint-color($danger, 40%);
$light-text-emphasis-dark:          $gray-100;
$dark-text-emphasis-dark:           $gray-300;
// scss-docs-end theme-text-dark-variables

// scss-docs-start theme-bg-subtle-dark-variables
$primary-bg-subtle-dark:            shade-color($primary, 80%);
$secondary-bg-subtle-dark:          shade-color($secondary, 80%);
$success-bg-subtle-dark:            shade-color($success, 80%);
$info-bg-subtle-dark:               shade-color($info, 80%);
$warning-bg-subtle-dark:            shade-color($warning, 80%);
$danger-bg-subtle-dark:             shade-color($danger, 80%);
$light-bg-subtle-dark:              $gray-800;
$dark-bg-subtle-dark:               mix($gray-800, $black);
// scss-docs-end theme-bg-subtle-dark-variables

// scss-docs-start theme-border-subtle-dark-variables
$primary-border-subtle-dark:        shade-color($primary, 40%);
$secondary-border-subtle-dark:      shade-color($secondary, 40%);
$success-border-subtle-dark:        shade-color($success, 40%);
$info-border-subtle-dark:           shade-color($info, 40%);
$warning-border-subtle-dark:        shade-color($warning, 40%);
$danger-border-subtle-dark:         shade-color($danger, 40%);
$light-border-subtle-dark:          $gray-700;
$dark-border-subtle-dark:           $gray-800;
// scss-docs-end theme-border-subtle-dark-variables

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


//
// Forms
//

$form-select-indicator-color-dark:  $body-color-dark;
$form-select-indicator-dark:        url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='#{$form-select-indicator-color-dark}' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>");

$form-switch-color-dark:            rgba($white, .25);
$form-switch-bg-image-dark:         url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-color-dark}'/></svg>");

// scss-docs-start form-validation-colors-dark
$form-valid-color-dark:             $green-300;
$form-valid-border-color-dark:      $green-300;
$form-invalid-color-dark:           $red-300;
$form-invalid-border-color-dark:    $red-300;
// scss-docs-end form-validation-colors-dark


//
// Accordion
//

$accordion-icon-color-dark:         $primary-text-emphasis-dark;
$accordion-icon-active-color-dark:  $primary-text-emphasis-dark;

$accordion-button-icon-dark:         url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/></svg>");
$accordion-button-active-icon-dark:  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-active-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/></svg>");

Sass mixin

深色模式的样式以及您创建的任何自定义颜色模式都可以适当地限定为data-bs-theme属性选择器,或使用可自定义的color-mode()mixin进行媒体查询。有关更多详细信息,请参阅 Sass 用法部分

@mixin color-mode($mode: light, $root: false) {
  @if $color-mode-type == "media-query" {
    @if $root == true {
      @media (prefers-color-scheme: $mode) {
        :root {
          @content;
        }
      }
    } @else {
      @media (prefers-color-scheme: $mode) {
        @content;
      }
    }
  } @else {
    [data-bs-theme="#{$mode}"] {
      @content;
    }
  }
}