data-bs-theme="dark" 必须作用于 <html> 元素才能影响表单组件,因其依赖 :root 下由 _variables-dark.scss 编译生成的 CSS 变量(如 --bs-form-control-bg),且需调用 Theme.update() 刷新变量并配合 localStorage 持久化。

data-bs-theme="dark" 必须作用于 才能影响表单组件
Bootstrap 5.3+ 的表单控件(input、select、textarea、form-check 等)默认读取 :root 下的 CSS 变量(如 --bs-form-control-bg、--bs-form-control-color),而这些变量只在 [data-bs-theme="dark"] 作用于 document.documentElement(即 <html>)时才会被重定义。加在 <form> 或某个 <div> 上,input 依然按浅色渲染。
常见错误现象:<form data-bs-theme="dark"><input class="form-control"></form> 表单背景仍是白的 —— 因为 form-control 的背景色来自根级变量,不是父级继承。
- 正确写法:
<html data-bs-theme="dark">(服务端初始可设"light",JS 加载后覆盖) - 局部测试可用:
<div class="form" data-bs-theme="dark">,但仅当该div是form-control的直接父容器且未被其他样式干扰时才可能生效 - Toast、Dropdown、Offcanvas 等挂载到
document.body的浮层组件,若<html>没设data-bs-theme,它们永远用浅色主题
表单颜色变量必须由 Bootstrap 自带 _variables-dark.scss 编译生成
如果你用 Sass 自定义构建 Bootstrap,input 在深色模式下的背景、边框、文字色是否变化,取决于 bootstrap/scss/_variables-dark.scss 是否参与编译。漏掉它,--bs-form-control-bg 等变量在 [data-bs-theme="dark"] 下仍是空值或 fallback 值,导致表单“看起来没变暗”。
检查方法:打开 DevTools → Elements → :root → 切换 data-bs-theme 值,看 --bs-form-control-bg 是否从 #fff 变成 #212529 类似的暗色值。
- CDN 用户无需操心:BootCDN 上的 5.3.3+ 版本已包含完整暗色变量
- npm 安装用户需确认
@import "bootstrap/scss/root";已引入,且未禁用$enable-dark-mode: true - 别手动在 CSS 里重写
.form-control { background: #343a40 }—— 这会绕过变量体系,升级后易断裂
切换主题后必须调用 bootstrap.Theme.getOrCreateInstance().update()
只执行 document.documentElement.setAttribute('data-bs-theme', 'dark'),input 的背景和文字色不会实时更新。因为 Bootstrap 不监听 DOM 属性变化,CSS 变量需要显式刷新。
尤其在表单场景下,用户点击切换按钮后如果没看到 input 变暗,大概率卡在这一步。
- ESM 环境(Vite/Next.js):
import { Theme } from 'bootstrap'; new Theme(document.documentElement).update(); - UMD 环境(CDN):
bootstrap.Theme.getOrCreateInstance(document.documentElement).update();,需确保bootstrap/js/dist/theme.js已加载(bootstrap.bundle.min.js不含它) - SSR 场景(如 Next.js):必须在
useEffect或DOMContentLoaded后执行,且 DOM 已挂载
prefers-color-scheme 不能替代 localStorage 持久化
浏览器能通过 window.matchMedia('(prefers-color-scheme: dark)') 拿到系统偏好,但它只是快照,不响应后续系统设置变更;更重要的是,它无法记住用户手动切换后的选择。比如用户在亮色模式下点按钮切到深色,关掉页面再打开,又回到系统默认 —— 表单又变亮了。
所以初始化逻辑必须是:先读 localStorage.getItem('theme'),无值再 fallback 到系统偏好。
- 存值必须用字符串:
localStorage.setItem('theme', 'dark'),不能存true或1 - 每次切换按钮点击,都要同步写入
localStorage并调用.update() - 服务端永远输出
<html data-bs-theme="light">,避免 SSR 渲染闪屏(尤其深色背景 + 浅色 placeholder 文字时)


















