Bootstrap 4 不支持 data-bs-theme,必须用 class 切换:需将 bootstrap-dark 类加在 body 上,确保暗黑 CSS 在 Bootstrap 主 CSS 之后加载,并手动切换 class 且适配自定义组件样式。
data-bs-theme,必须用 class 切换Bootstrap 4 官方没有 data-bs-theme 属性机制,所有主题切换都依赖 CSS class(如 bootstrap-dark)驱动。你不能照搬 Bootstrap 5.3+ 的写法——改 document.documentElement.setAttribute('data-bs-theme', 'dark') 在 v4 下完全无效。
主流方案是引入第三方暗黑主题包(如 @forevolve/bootstrap-dark),它通过覆盖原有类名样式实现切换。核心逻辑是:<body class="bootstrap-dark"> 触发整套深色样式重载,而非变量更新。
<body> 上,加在 <html> 或容器 div 里不起作用bootstrap-dark.min.css 在 bootstrap.min.css 之后加载,否则样式被覆盖bootstrap-dark 和自定义 dark.css),容易因选择器优先级冲突导致部分组件不生效Bootstrap 4 没有 bootstrap.Theme.getOrCreateInstance().update() 这类 API,也没有 CSS 变量重计算机制。所谓“切换”,本质是 DOM class 变更 + 浏览器重新匹配样式规则。
典型实现就是操作 document.body.className:
立即学习“前端免费学习笔记(深入)”;
const toggleBtn = document.getElementById('theme-toggle');toggleBtn.addEventListener('click', () => { const body = document.body; if (body.classList.contains('bootstrap-dark')) { body.classList.remove('bootstrap-dark'); localStorage.setItem('theme', 'light'); } else { body.classList.add('bootstrap-dark'); localStorage.setItem('theme', 'dark'); }});
setAttribute('class', ...) 全量覆盖,会丢掉其他必要 class(如 container 所在的 wrapper 类)localStorage.getItem('theme') 读取,而不是只看 prefers-color-scheme,否则用户上次选择丢失$('body').removeClass().addClass() 这种粗暴写法——它会清空所有 class,应改用 .toggleClass('bootstrap-dark')
Bootstrap 4 的按钮、卡片等组件样式写死在 CSS 里(比如 .btn-primary { background-color: #007bff; }),bootstrap-dark 包只是提供了另一套同名 class 的重写规则。但你自己写的 .card-dashboard 或 .stat-badge 不会自动响应 body.bootstrap-dark ——除非你主动写对应规则。
正确写法是利用父级 class 做作用域限定:
.card-dashboard { background-color: #f8f9fa; color: #212529;}body.bootstrap-dark .card-dashboard { background-color: #212529; color: #f8f9fa;}
.card-dashboard 内部用 var(--bs-bg) —— Bootstrap 4 根本没定义这些变量!important 强行覆盖,优先靠选择器权重(如 body.bootstrap-dark .btn 比 .btn 优先级高)window.matchMedia('(prefers-color-scheme: dark)') 返回的是当前快照,不是响应式信号。Bootstrap 4 本身不监听这个事件,也不会在系统主题切换时自动翻转 body 的 class。
若需自动响应,得自己补监听逻辑:
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');function handleThemeChange(e) { const theme = e.matches ? 'dark' : 'light'; if (localStorage.getItem('theme') === null) { document.body.classList.toggle('bootstrap-dark', e.matches); }}mediaQuery.addEventListener('change', handleThemeChange);handleThemeChange(mediaQuery); // 立即执行一次
localStorage 为空时才按系统偏好设置,否则尊重用户手动选择DOMContentLoaded 之后才绑定监听器,否则可能错过首次触发