Перейти к основному содержанию Перейти к навигации по документации
Добавлено в v5.3 На GitHub

Цветовые режимы

Bootstrap теперь поддерживает цветовые режимы или темы, начиная с версии 5.3.0. Изучите наш светлый цветовой режим по умолчанию и новый темный режим или создайте свой собственный, используя наши стили в качестве шаблона.

Попробуйте сами! Загрузите исходный код и рабочую демонстрацию для использования Bootstrap со Stylelint, а также цветовые режимы из репозитория twbs/examples. Вы также можете открыть пример в StackBlitz.

Темный режим

Bootstrap теперь поддерживает цветовые режимы, начиная с темного режима! В версии 5.3.0 вы можете реализовать собственный переключатель цветового режима (см. ниже пример из документации Bootstrap) и применять различные цветовые режимы по своему усмотрению. Мы поддерживаем светлый режим (по умолчанию), а теперь и темный режим. Цветовые режимы можно переключать глобально для элемента <html> или для определенных компонентов и элементов благодаря атрибуту data-bs-theme.

Кроме того, вы также можете переключиться на реализацию медиа-запроса благодаря нашему миксину цветового режима — смотрите подробности в разделе об использовании. Однако обратите внимание — это лишает вас возможности изменять темы для каждого компонента, как показано ниже.

Пример

Например, чтобы изменить цветовой режим выпадающего меню, добавьте 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">
    Раскрывающийся список по умолчанию
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButtonLight">
    <li><a class="dropdown-item active" href="#">Действие</a></li>
    <li><a class="dropdown-item" href="#">Действие</a></li>
    <li><a class="dropdown-item" href="#">Другое действие</a></li>
    <li><a class="dropdown-item" href="#">Что-то еще здесь</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">Отделенная ссылка</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">
    Темный раскрывающийся список
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButtonDark">
    <li><a class="dropdown-item active" href="#">Действие</a></li>
    <li><a class="dropdown-item" href="#">Действие</a></li>
    <li><a class="dropdown-item" href="#">Другое действие</a></li>
    <li><a class="dropdown-item" href="#">Что-то еще здесь</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">Отделенная ссылка</a></li>
  </ul>
</div>

Как это работает

  • Как показано выше, стили цветового режима управляются атрибутом data-bs-theme. Этот атрибут можно применить к элементу <html> или к любому другому элементу или компоненту Bootstrap. Если применить к элементу <html>, он будет применяться ко всему. Если оно применяется к компоненту или элементу, оно будет ограничено этим конкретным компонентом или элементом.

  • Для каждого цветового режима, который вы хотите поддерживать, вам нужно будет добавить новые переопределения для общих глобальных переменных CSS. Мы делаем это уже в нашей таблице стилей _root.scss для темного режима, при этом светлый режим является значением по умолчанию. При написании стилей, специфичных для цветового режима, используйте миксин:

    // Color mode variables in _root.scss
    @include color-mode(dark) {
      // CSS variable overrides here...
    }
    
  • Мы используем пользовательский _variables-dark.scss, чтобы включить эти общие глобальные переопределения переменных CSS для темного режима. Этот файл не требуется для ваших собственных пользовательских цветовых режимов, но он необходим для нашего темного режима по двум причинам. Во-первых, лучше иметь одно место для сброса глобальных цветов. Во-вторых, некоторые переменные Sass пришлось переопределить для фоновых изображений, встроенных в наш CSS для аккордеонов, компонентов форм и многого другого.

Применение

Включить темный режим

Включите встроенный режим темного цвета во всем проекте, добавив атрибут 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/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
  </head>
  <body>
    <h1>Hello, world!</h1>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
  </body>
</html>

Bootstrap еще не поставляется со встроенным средством выбора цветового режима, но вы можете использовать его из нашей собственной документации, если хотите. Подробнее в разделе JavaScript.

Создание с помощью Sass

Наша новая опция темного режима доступна для всех пользователей Bootstrap, но она управляется с помощью атрибутов данных, а не медиа-запросов, и не переключает автоматически цветовой режим вашего проекта. Вы можете полностью отключить наш темный режим через Sass, изменив $enable-dark-mode на false.

Мы используем собственный миксин Sass, color-mode(), чтобы помочь вам управлять тем, как применяются цветовые режимы. По умолчанию мы используем атрибут data, что позволяет вам создавать более удобный интерфейс, где ваши посетители могут выбрать автоматический темный режим или управлять своими предпочтениями (как в наших собственных документах здесь). Это также простой и масштабируемый способ добавления различных тем и дополнительных пользовательских цветовых режимов помимо светлого и темного.

Если вы хотите использовать медиа-запросы и сделать автоматическими только цветовые режимы, вы можете изменить тип миксина по умолчанию с помощью переменной Sass. Рассмотрим следующий фрагмент и его скомпилированный вывод 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 для размещения переменных Sass, специфичных для темного режима Bootstrap, но это не обязательно для вас.

Например, вы можете создать «синюю тему» с помощью селектора data-bs-theme="blue". В свой пользовательский файл Sass или CSS добавьте новый селектор и при необходимости переопределите любые глобальные или компонентные переменные CSS. Если вы используете Sass, вы также можете использовать функции Sass в своих переопределениях переменных CSS.

[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);
  }
}
Пример синей темы

Некоторый текст абзаца, чтобы показать, как синяя тема может выглядеть с письменной копией.


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

JavaScript

Чтобы разрешить посетителям или пользователям переключать цветовые режимы, вам необходимо создать элемент переключения для управления атрибутом data-bs-theme в корневом элементе <html>. В нашей документации мы создали переключатель, который изначально зависит от текущего системного цветового режима пользователя, но предоставляет возможность переопределить его и выбрать определенный цветовой режим.

Вот посмотрите на JavaScript, на котором он работает. Не стесняйтесь проверять нашу собственную панель навигации документации, чтобы увидеть, как она реализована с использованием HTML и CSS из наших собственных компонентов. Рекомендуется включить JavaScript в верхней части страницы, чтобы уменьшить потенциальное мерцание экрана во время перезагрузки вашего сайта. Обратите внимание: если вы решите использовать медиа-запросы для своих цветовых режимов, возможно, потребуется изменить или удалить ваш JavaScript, если вы предпочитаете неявный контроль.

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

(() => {
  'use strict'

  const getStoredTheme = () => localStorage.getItem('theme')
  const setStoredTheme = theme => localStorage.setItem('theme', theme)

  const getPreferredTheme = () => {
    const storedTheme = getStoredTheme()
    if (storedTheme) {
      return storedTheme
    }

    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
  }

  const setTheme = theme => {
    if (theme === 'auto') {
      document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
    } 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', () => {
    const storedTheme = getStoredTheme()
    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')
          setStoredTheme(theme)
          setTheme(theme)
          showActiveTheme(theme, true)
        })
      })
  })
})()

Добавление цветов темы

Добавления нового цвета в $theme-colors недостаточно для некоторых наших компонентов, таких как alerts и list groups. Новые цвета также должны быть определены в $theme-colors-text, $theme-colors-bg-subtle и $theme-colors-border-subtle для светлой темы; но также и в $theme-colors-text-dark, $theme-colors-bg-subtle-dark и $theme-colors-border-subtle-dark для темной темы.

Это ручной процесс, потому что Sass не может генерировать свои собственные переменные Sass из существующей переменной или карты. В будущих версиях Bootstrap мы вернемся к этой настройке, чтобы уменьшить дублирование.

// Required
@import "functions";
@import "variables";
@import "variables-dark";

// Add a custom color to $theme-colors
$custom-colors: (
  "custom-color": #712cf9
);
$theme-colors: map-merge($theme-colors, $custom-colors);

@import "maps";
@import "mixins";
@import "utilities";

// Add a custom color to new theme maps

// Light mode
$custom-colors-text: ("custom-color": #712cf9);
$custom-colors-bg-subtle: ("custom-color": #e1d2fe);
$custom-colors-border-subtle: ("custom-color": #bfa1fc);

$theme-colors-text: map-merge($theme-colors-text, $custom-colors-text);
$theme-colors-bg-subtle: map-merge($theme-colors-bg-subtle, $custom-colors-bg-subtle);
$theme-colors-border-subtle: map-merge($theme-colors-border-subtle, $custom-colors-border-subtle);

// Dark mode
$custom-colors-text-dark: ("custom-color": #e1d2f2);
$custom-colors-bg-subtle-dark: ("custom-color": #8951fa);
$custom-colors-border-subtle-dark: ("custom-color": #e1d2f2);

$theme-colors-text-dark: map-merge($theme-colors-text-dark, $custom-colors-text-dark);
$theme-colors-bg-subtle-dark: map-merge($theme-colors-bg-subtle-dark, $custom-colors-bg-subtle-dark);
$theme-colors-border-subtle-dark: map-merge($theme-colors-border-subtle-dark, $custom-colors-border-subtle-dark);

// Remainder of Bootstrap imports
@import "root";
@import "reboot";
// etc

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

--#{$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}highlight-color: #{$mark-color-dark};
--#{$prefix}highlight-bg: #{$mark-bg-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 для нашего темного цветового режима частично генерируются из переменных Sass, специфичных для темного режима, в _variables-dark.scss. Это также включает в себя некоторые пользовательские переопределения для изменения цветов встроенных SVG, используемых во всех наших компонентах.

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

$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);

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

$body-color-dark:                   $gray-300;
$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:               inherit;
$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%);
$mark-color-dark:                   $body-color-dark;
$mark-bg-dark:                      $yellow-800;


//
// 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>");

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


//
// 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 миксины

Стили для темного режима и любые пользовательские цветовые режимы, которые вы создаете, могут быть соответствующим образом привязаны к селектору атрибута data-bs-theme или медиа-запросу с помощью настраиваемого миксина color-mode(). Подробнее смотрите в разделе Использование 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;
    }
  }
}