必须用 css 变量接管 bootstrap 颜色体系,即在 :root 定义明色变量(如 --bs-body-bg: #fff),再于 [data-bs-theme="dark"] 中重定义暗色值(如 --bs-body-bg: #121212),并确保自定义 css 在 bootstrap.min.css 后加载,同时调用 bootstrap.theme.getorcreateinstance().update() 触发变量重计算。

必须用 CSS 变量接管 Bootstrap 颜色体系
Bootstrap 5.3+ 的暗黑模式不是靠 class 切换,而是依赖 CSS 自定义变量(如 --bs-body-bg、--bs-primary)在 :root 和 [data-bs-theme="dark"] 下的不同定义。如果你直接写 background-color: #121212 覆盖组件样式,就绕过了这套机制,后续切换会失效。
正确做法是:先在 :root 定义明色系变量,再用属性选择器覆盖暗色值。顺序不能错,否则变量读不到。
-
:root中定义所有基础变量(哪怕只用到其中几个),例如:--bs-body-bg: #fff;、--bs-body-color: #212529; -
[data-bs-theme="dark"]块内重写对应变量,例如:--bs-body-bg: #121212;、--bs-body-color: #e9ecef; - 确保你的自定义 CSS 在
bootstrap.min.css之后加载,否则变量会被 bootstrap 默认值覆盖 - 检查开发者工具中
:root节点下变量值是否随data-bs-theme切换而变化——这是最直接的验证方式
为什么加了 data-bs-theme="dark" 按钮却没变色
常见现象是 HTML 属性改了,但 <button class="btn btn-primary"></button> 仍是蓝底白字。根本原因不是 JS 没执行,而是 --bs-primary 这个变量压根没在 [data-bs-theme="dark"] 里重新赋值。
Bootstrap 组件内部用的是 var(--bs-primary),但它默认只在官方 bootstrap-dark.css 或 Sass 编译时启用的暗色变量中才被重定义。你若没手动补全,它就永远沿用浅色值。
- 必须显式写出:
[data-bs-theme="dark"] { --bs-primary: #6ea8ff; }(数值按设计稿调整) - 别漏掉边框、表单控件、卡片阴影等常用变量,比如
--bs-border-color、--bs-form-control-bg - 优先级不够时加
!important是临时解法,但说明你选择器层级或加载顺序有问题 - 局部组件(如
<div class="card" data-bs-theme="dark">)也依赖同一套变量,所以全局变量定义缺一不可 <h3> <code>prefers-color-scheme媒体查询怎么配合使用CSS 里的
@media (prefers-color-scheme: dark)本身不能设置 HTML 属性,也不能触发 Bootstrap 的变量重算。它只能作为初始值来源之一,且仅响应系统偏好,不记忆用户主动选择。真正可行的组合是:用 JS 检测媒体查询结果 + 设置
data-bs-theme+ 调用bootstrap.Theme.getOrCreateInstance().update()。CSS 媒体查询只用来兜底或做 SSR 初始渲染提示。- 媒体查询必须写在
:root变量定义之后,否则旧版 Safari 可能忽略 - 不要写成
@media (prefers-color-scheme) { ... }—— 必须带具体值:dark或light - 避免嵌套媒体查询,比如
@media (max-width: 768px) { @media (prefers-color-scheme: dark) { ... } },兼容性差 - 如果用户手动切过主题,就该以
localStorage为准,媒体查询结果仅作 fallback
切换后样式卡在旧值?漏了这一步
只改
document.documentElement.setAttribute('data-bs-theme', 'dark')是不够的。--bs-body-bg等变量不会自动重计算,浏览器仍沿用旧值。这是最常被跳过的硬性步骤。必须显式调用 Bootstrap 提供的主题更新方法,否则所有组件颜色、背景、边框都“冻住”不动。
- UMD 环境(CDN 引入
bootstrap.bundle.min.js):调用bootstrap.Theme.getOrCreateInstance(document.documentElement).update() - ESM 环境(
import { Theme } from 'bootstrap'):用new Theme(document.documentElement).update() - 传参必须是
document.documentElement,传document.body会静默失败或报错 - 这个调用要放在
setAttribute之后、且 DOM 已就绪(比如DOMContentLoaded后或 React 的useEffect中)
- 媒体查询必须写在











