Зарегистрируйтесь, чтобы продолжить обучение

Темная и светлая тема Bootstrap 5: Продвинутый уровень

В версии Bootstrap 5.3 появилась новая функция — возможность создавать светлую и темную темы для проекта. Теперь не нужно писать кастомные CSS-стили для создания нескольких тем. Всё настраивается через переменные.

В этом уроке мы разберем, как работает светлая и темная темы в Bootstrap. Так же изучим изменение темы и создание собственных.

Переключение светлой и темной тем

В Bootstrap 5.3 светлая и темная темы включены по умолчанию. Для них всё готово. Нужно лишь научится их переключать. Это можно сделать с помощью HTML-атрибута data-bs-theme, который принимает одно из двух значений:

  • light — светлая тема. Используется по умолчанию

  • dark — темная тема

Использовать атрибут можно на любом теге HTML, но чаще всего его ставят на весь <body>. Это позволяет задать тему сразу для всего проекта.

В примере ниже можно включать и выключать темную тему, чтобы посмотреть на все изменения:

See the Pen bootstrap_advanced_course_colors_3 by Hexlet (@hexlet) on CodePen.

Если посмотреть на изменения, можно заметить важную особенность — изменяется фон и цвет текста. Основные цвета, такие как primary и warning не изменяются, так как это основные цвета темы.

Также не изменяются размеры элементов, их расположение, внутренние и внешние отступы. Всё это не относится к изменениям темы, но можно влиять даже на это с помощью миксина color-mode.

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

Изменение темной темы

В уроке про изменение цветовой схемы мы создали новую пастельную схему. Вот как она выглядела:

Цветовая схема для Bootstrap

Ее цвета не такие «агрессивные» для использования на темном фоне. Поэтому сделаем смену основных цветов только для темной темы. Для этого продолжим изменять файл brand-color.scss, который был создан в уроке про цветовые схемы. Вот как он выглядел:

@use "sass:map";

$brand-theme-colors: (
  "primary": #a8d8ea,
  "secondary": #aa96da,
  "success": #bbfcba,
  "danger": #fcbad3,
  "warning": #ffffd2,
  "info": #96a9da,
);

$primary:   map.get($brand-theme-colors, "primary");
$secondary: map.get($brand-theme-colors, "secondary");
$success:   map.get($brand-theme-colors, "success");
$info:      map.get($brand-theme-colors, "info");
$warning:   map.get($brand-theme-colors, "warning");
$danger:    map.get($brand-theme-colors, "danger");

Чтобы переделать цвета только для темной темы, нужно будет пойти на небольшие хитрости:

  1. Создать новые массивы $theme-colors и $theme-colors-rgb

  2. Сгенерировать новые переменные цветовой схемы

  3. Обернуть все переменные и функции в миксин color-mode с аргументом dark

  4. Изменить порядок подключения файлов в файле main.scss

Пойдем по порядку. Создадим массивы $theme-colors и $theme-colors-rgb. Это создаст новую цветовую схему, которую в последствии будем использовать только для элементов с атрибутом data-bs-theme="dark":

$brand-theme-colors: (
  "primary":   #a8d8ea,
  "secondary": #aa96da,
  "success":   #bbfcba,
  "danger":    #fcbad3,
  "warning":   #ffffd2,
  "info":      #96a9da,
);

$primary:   map.get($brand-theme-colors, "primary");
$secondary: map.get($brand-theme-colors, "secondary");
$success:   map.get($brand-theme-colors, "success");
$info:      map.get($brand-theme-colors, "info");
$warning:   map.get($brand-theme-colors, "warning");
$danger:    map.get($brand-theme-colors, "danger");

$theme-colors: (
  "primary":   $primary,
  "secondary": $secondary,
  "success":   $success,
  "danger":    $danger,
  "warning":   $warning,
  "info":      $info,
);

// С помощью функции to-rgb()
// переводим цвета в формат RGB

$theme-colors-rgb: (
  "primary":   to-rgb($primary),
  "secondary": to-rgb($secondary),
  "success":   to-rgb($success),
  "danger":    to-rgb($danger),
  "warning":   to-rgb($warning),
  "info":      to-rgb($info),
);

Важно, что мы создаем массив $theme-colors-rgb, где все цвета переводятся в модель rgb. В таком формате используются цвета в некоторых компонентах. Например, в формате RGB используются цвета в тексте:

.text-info {
  --bs-text-opacity: 1;
  color: rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important;
}

/* --bs-info-rgb: 13,202,240; */

Теперь используем новые массивы и сгенерируем цвета. Для этого используем два цикла, которые сгенерируют переменные:

// Генерация переменных из массива $theme-colors
@each $color, $value in $theme-colors {
  --#{$prefix}#{$color}: #{$value};
}

// Генерация переменных из массива $theme-colors-rgb
@each $color, $value in $theme-colors-rgb {
  --#{$prefix}#{$color}-rgb: #{$value};
}

Этот код сгенерирует 12 переменных:

--bs-primary: #a8d8ea;
--bs-secondary: #aa96da;
--bs-success: #bbfcba;
--bs-danger: #fcbad3;
--bs-warning: #ffffd2;
--bs-info: #96a9da;
--bs-primary-rgb: 168, 216, 234;
--bs-secondary-rgb: 170, 150, 218;
--bs-success-rgb: 187, 252, 186;
--bs-danger-rgb: 252, 186, 211;
--bs-warning-rgb: 255, 255, 210;
--bs-info-rgb: 150, 169, 218;

Чтобы эти переменные использовались только на темной теме, весь написанный код нужно обернуть в миксин color-mode со значением dark. Это добавит переменные в CSS-селектор [data-bs-theme=dark]:

@use "sass:map";

@include color-mode(dark) {
  $brand-theme-colors: (
    "primary": #a8d8ea,
    "secondary": #aa96da,
    "success": #bbfcba,
    "danger": #fcbad3,
    "warning": #ffffd2,
    "info": #96a9da,
  );

  $primary:   map.get($brand-theme-colors, "primary");
  $secondary: map.get($brand-theme-colors, "secondary");
  $success:   map.get($brand-theme-colors, "success");
  $info:      map.get($brand-theme-colors, "info");
  $warning:   map.get($brand-theme-colors, "warning");
  $danger:    map.get($brand-theme-colors, "danger");

  $theme-colors: (
    "primary": $primary,
    "secondary": $secondary,
    "success": $success,
    "danger": $danger,
    "warning": $warning,
    "info": $info,
  );

  $theme-colors-rgb: (
    "primary": to-rgb($primary),
    "secondary": to-rgb($secondary),
    "success": to-rgb($success),
    "danger": to-rgb($danger),
    "warning": to-rgb($warning),
    "info": to-rgb($info),
  );

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

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

Осталось подключить файл с цветовой схемой. Тут есть хитрость — подключить файл уже после подключения фреймворка. В Bootstrap еще не отточена система с изменением темной цветовой схемы, так как нет отдельного массива $theme-colors в настройках проекта.

По этой причине вначале полностью подключается Bootstrap, а затем отдельно подключается новая темная цветовая схема.

@import "../../node_modules/bootstrap/scss/bootstrap.scss";
@import "./brand-color";

После компиляции в CSS-файле появится следующий код:

[data-bs-theme=dark] {
  --bs-primary: #a8d8ea;
  --bs-secondary: #aa96da;
  --bs-success: #bbfcba;
  --bs-danger: #fcbad3;
  --bs-warning: #ffffd2;
  --bs-info: #96a9da;
  --bs-primary-rgb: 168, 216, 234;
  --bs-secondary-rgb: 170, 150, 218;
  --bs-success-rgb: 187, 252, 186;
  --bs-danger-rgb: 252, 186, 211;
  --bs-warning-rgb: 255, 255, 210;
  --bs-info-rgb: 150, 169, 218;
}

Добавим этот CSS в наш первый пример. Теперь при переключении темы меняются и основные цвета проекта:

See the Pen bootstrap_advanced_course_dark-theme_1 by Hexlet (@hexlet) on CodePen.

Выводы

В Bootstrap 5.3 появилась возможность использовать несколько цветовых схем. Главным мотиватором такого решения стала возможность добавлять светлую и темную тему для проекта.

Переключение тем происходит с помощью изменения атрибута data-bs-theme. Этот атрибут может использоваться как на отдельном компоненте, так и на всем проекте. Для всего проекта атрибут устанавливают для тега <html> или <body>. Чтобы установить темную тему, используется значение dark.

Чтобы добавить произвольные цвета в цветовую схему для темной темы, используется следующий алгоритм:

  1. Создаются новые массивы $theme-colors и $theme-colors-rgb

  2. С помощью циклов генерируются CSS-переменные из созданных массивов

  3. Весь код оборачивается в миксин color-mode с аргументом dark. Это позволит сгенерировать переменные только для селектора [data-bs-theme=dark]

  4. В основном файле проекта новые цвета подключаются уже после подключения всего фреймворка


Самостоятельная работа

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


Дополнительные материалы

  1. Color modes

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»