Тёмная тема
С версии 5.3 в Bootstrap встроены цветовые режимы: светлый и тёмный. Режим включается одним атрибутом data-bs-theme, и все компоненты — карточки, таблицы, формы, меню — сами перекрашиваются. Отдельные стили для тёмной темы писать не нужно.
Тема для всей страницы
Атрибут ставят на тег <html>:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script>document.documentElement.setAttribute('data-bs-theme', 'dark');</script>
<div class="card" style="max-width: 18rem">
<div class="card-body">
<h5 class="card-title">Тёмная карточка</h5>
<input class="form-control mb-2" placeholder="Название задачи">
<button type="button" class="btn btn-primary">Добавить</button>
</div>
</div>В превью нет своего тега <html>, поэтому атрибут ставит строка JavaScript. В вашем index.html достаточно написать <html lang="ru" data-bs-theme="dark">. Фон страницы, карточка и поле стали тёмными, текст — светлым, а синяя кнопка осталась синей.
Тема для одного блока
Атрибут работает на любом элементе и действует на всё внутри. Так можно сделать тёмной только шапку или боковое меню админ-панели:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<div class="d-flex border">
<div class="bg-body text-body p-3" data-bs-theme="dark" style="width: 160px">
<div class="fw-bold mb-2">Tasko</div>
<div class="text-body-secondary">Обзор</div>
<div class="text-body-secondary">Заказы</div>
</div>
<div class="bg-body text-body p-3 flex-grow-1">Светлая основная часть</div>
</div>Левое меню тёмное, правая часть светлая. Классы bg-body и text-body берут фон и цвет текста текущей темы, поэтому одна и та же разметка выглядит правильно в обеих темах.
Переключатель темы
Тема — это просто атрибут, значит, переключатель меняет его из JavaScript:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="themeSwitch">
<label class="form-check-label" for="themeSwitch">Тёмная тема</label>
</div>
<script>
const root = document.documentElement;
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const themeSwitch = document.querySelector('#themeSwitch');
root.setAttribute('data-bs-theme', prefersDark ? 'dark' : 'light');
themeSwitch.checked = prefersDark;
themeSwitch.addEventListener('change', () => {
root.setAttribute('data-bs-theme', themeSwitch.checked ? 'dark' : 'light');
});
</script>При загрузке тема совпадает с настройкой операционной системы: matchMedia проверяет медиазапрос prefers-color-scheme. Щёлкните переключатель — превью сменит тему. В реальном проекте выбор пользователя ещё сохраняют в localStorage, чтобы он не сбрасывался при перезагрузке.
Частая ошибка
Красить блоки классами bg-white, bg-light, text-dark. Это постоянные цвета: в тёмной теме такой блок останется белым с тёмным текстом посреди тёмной страницы. Для фона и текста, которые должны следовать за темой, используйте bg-body, bg-body-tertiary, text-body и text-body-secondary.