Bootstrap 5.3+ 深色模式需同时设置 data-bs-theme 属性并调用 bootstrap.Theme.getOrCreateInstance().update() 重算 CSS 变量,UMD 需额外引入 theme.js,自定义组件须用 var(--bs-*) 变量并确保 CSS 在 Bootstrap 后加载且正确覆盖。

只设 data-bs-theme="dark" 不会生效,必须同步刷新 CSS 变量值——这是绝大多数人卡住的第一步。
为什么 document.documentElement.setAttribute('data-bs-theme', 'dark') 没反应
根本不是 JS 写错了,而是 --bs-body-bg 这类变量压根没重算。Bootstrap 5.3+ 的深色模式依赖属性触发 + 变量重计算双机制,漏掉后者,样式就冻结在初始状态。
- 打开浏览器开发者工具 → 查看
:root节点 → 切换后--bs-body-bg值不变?说明bootstrap.Theme.getOrCreateInstance().update()没执行 - 用 UMD 方式引入(比如
bootstrap.bundle.min.js)时,bootstrap.Theme默认不可用,必须额外加载bootstrap/js/dist/theme.js - ESM 环境下需确保已
import 'bootstrap/js/dist/theme',否则调用会报Cannot read properties of undefined - 调用时推荐传参
document.documentElement:bootstrap.Theme.getOrCreateInstance(document.documentElement).update(),避免实例作用域错位
如何让自定义组件也响应 data-bs-theme 切换
你写的 .card-dashboard、.badge-status 不会自动变色,因为它们没读 CSS 变量——Bootstrap 只管自己的 btn、card,不接管你的代码。
- 所有自定义颜色必须用
var(--bs-body-bg)、var(--bs-primary),不能硬写#fff或rgb(33, 37, 41) - 在 Bootstrap CSS 之后加载你的自定义 CSS,并显式声明两套变量:
:root定义浅色值,[data-bs-theme="dark"]覆盖深色值 - 顺序不能错:先
:root { --bs-primary: #0d6efd; },再[data-bs-theme="dark"] { --bs-primary: #6ea8ff; } - 检查“计算样式”里背景色是否解析为深色值——如果不是,要么变量没覆盖,要么选择器优先级不够(可加
!important临时验证)
切换按钮的最小可行闭环逻辑
点击一次只改属性,下次刷新就回退;图标和实际主题脱节,用户会困惑。完整链路必须包含四件事:改属性、存本地、刷变量、更新 UI。
立即学习“前端免费学习笔记(深入)”;
- 按钮点击时,读当前
data-bs-theme值:const current = document.documentElement.getAttribute('data-bs-theme') || 'light' - 计算下一个值:
const next = current === 'light' ? 'dark' : 'light' - 三件事同步做:
document.documentElement.setAttribute('data-bs-theme', next)+localStorage.setItem('theme', next)+bootstrap.Theme.getOrCreateInstance(document.documentElement).update() - 图标更新别靠 toggle 类名猜状态,应直接根据
next决定:icon.classList.toggle('fa-sun', next === 'light')、icon.classList.toggle('fa-moon', next === 'dark')
最容易被忽略的是:CSS 加载顺序和变量覆盖层级。哪怕 JS 全对,只要自定义 CSS 写在 Bootstrap 之前,或用了硬编码颜色,data-bs-theme 就形同虚设。


















