bootstrap 5.3+ 原生支持暗色模式,需在 html 或 body 上设置 data-bs-theme="dark" 并确保加载对应 css 变量;须结合 prefers-color-scheme 检测系统偏好、localstorage 持久化状态,并手动处理自定义组件与图标适配。

Bootstrap 5.3+ 原生支持 dark mode,但默认不启用
Bootstrap 5.3 起通过 data-bs-theme="dark" 属性和 CSS 变量实现了暗色主题基础能力,但它不会自动检测系统偏好或切换主题——你得自己补上触发逻辑和持久化机制。
常见错误现象:data-bs-theme="dark" 加了但页面没变黑,是因为 Bootstrap 的暗色样式只在 :root 或 html 元素上生效,且依赖预编译的 CSS 变量(比如 --bs-body-bg),没加载对应变量值就只是个空壳。
- 必须确保使用的是 Bootstrap 5.3 或更高版本(检查
bootstrap.min.css文件头注释) - 不能只给某个 div 加
data-bs-theme="dark",要加在或上才全局生效 - 如果用 Sass 自定义构建,需启用
$enable-dark-mode: true并 importscss/mixins/_color-mode.scss
用 prefers-color-scheme 检测系统偏好并初始化
浏览器原生支持 prefers-color-scheme 媒体查询,这是最轻量、最可靠的初始判断方式。但注意:它只在页面加载时读取一次,不能监听后续系统切换(除非手动监听 matchMedia 变化)。
使用场景:用户首次访问时自动匹配系统设置,避免白屏/闪动。
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-bs-theme', 'dark');
} else {
document.documentElement.setAttribute('data-bs-theme', 'light');
}
- 别用
localStorage初始化前就覆盖这个判断——否则用户手动切过主题后,下次进站又会回到系统设置 - 移动端 Safari 对
matchMedia支持良好,但旧版 Android WebView 可能不支持,可加降级逻辑(如默认 light) - 不要在
DOMContentLoaded之前读取matchMedia,否则可能取不到值
切换按钮 + localStorage 持久化主题状态
用户点击切换时,要同时更新 DOM 属性、localStorage 和可选的 prefers-color-scheme 监听器。容易踩的坑是:只改了 data-bs-theme 却没同步存到本地,刷新后还原;或者存了但没在初始化时读取。
参数差异:localStorage.setItem('theme', 'dark') 是字符串,不是布尔值,别写成 true。
function toggleTheme() {
const current = document.documentElement.getAttribute('data-bs-theme') || 'light';
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-bs-theme', next);
localStorage.setItem('theme', next);
}
// 页面加载时读取
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.documentElement.setAttribute('data-bs-theme', savedTheme);
}
- 别用
sessionStorage——它关掉标签页就丢,不符合“夜间模式”预期 - 切换按钮的
aria-pressed状态建议同步更新,方便屏幕阅读器识别 - 如果用了 Webpack/Vite,注意某些 CSS 提取插件会把
:root[data-bs-theme="dark"]规则删掉,需检查最终 CSS 是否包含暗色变量定义
自定义组件暗色样式兼容性处理
Bootstrap 的暗色模式只覆盖了官方组件(.btn、.card、.table 等)的基础变量,你写的自定义 class 或第三方组件(比如 .my-header)不会自动变色。
性能影响:用 @media (prefers-color-scheme: dark) 写额外 CSS 规则没问题,但若大量重复写 html[data-bs-theme="dark"] .my-xxx,不如直接复用 Bootstrap 的 CSS 变量,减少冗余。
.my-card {
background-color: var(--bs-body-bg);
color: var(--bs-body-color);
}
- 别直接写
background: #343a40——这样在暗色模式下反而变成深灰底深灰字,看不见 - 第三方图标库(如 Font Awesome)通常不响应
data-bs-theme,需单独加html[data-bs-theme="dark"] .fa规则 - 表单控件(
<input>、<select></select>)的原生样式由操作系统渲染,CSS 变量无法控制,必要时用appearance: none+ 自绘
最麻烦的其实是图片和 SVG 图标——它们不会随主题变色,得准备两套资源或用 filter: invert(1) 这类 hack,但后者会影响可读性。这事没银弹,得一个个看。











