正确做法是在HTML源码中直接写死data-bs-theme属性,服务端或内联JS同步设置,并调用bootstrap.Theme.update()强制刷新CSS变量,同时声明color-scheme: light dark以确保原生控件适配。

必须在 HTML 标签写死 data-bs-theme,不能等 JS 加载后才设
闪屏本质是“先亮后暗”:浏览器渲染第一帧时,document.documentElement还没被 JS 修改,CSS 变量按默认值计算,页面先以亮色呈现,JS 执行完再跳变。哪怕只延迟几十毫秒,人眼就能感知。
正确做法是在服务端或 HTML 源码里直接写:<html lang="zh-CN" data-bs-theme="light">(或 "dark",取决于用户上次选择)。这样首屏直出即为最终主题,零闪动。
- 用
localStorage读取上次偏好,但必须在<head>内联 JS 中同步执行,不能等DOMContentLoaded - Next.js / Nuxt 等 SSR 框架,需在服务端根据请求头或 cookie 判断初始主题,注入到 HTML 字符串中
- 千万别写
document.body.setAttribute('data-bs-theme', ...)—— 这个属性对:root变量完全无效
bootstrap.Theme.getOrCreateInstance().update() 不是可选,是强制步骤
只改 data-bs-theme 属性,Bootstrap 的 CSS 自定义变量(如 --bs-body-bg)不会自动重算。你看到的“没变化”,往往就是漏了这行调用。
必须显式触发更新:
立即学习“前端免费学习笔记(深入)”;
- UMD 版本(
bootstrap.bundle.min.js):确保已加载bootstrap/js/dist/theme.js,然后调用bootstrap.Theme.getOrCreateInstance(document.documentElement).update() - ESM 版本(
import { Theme } from 'bootstrap'):用new Theme(document.documentElement).update() - SSR 场景下,此调用必须放在
useEffect或DOMContentLoaded后,且 DOM 已挂载
别混用 @media (prefers-color-scheme: dark) 和手动切换逻辑
媒体查询本身不响应运行时变化,它只是快照;而用户点击“切暗色”是主动行为。两者信号源不同,硬凑一起必然打架——比如系统是亮色,用户切了暗色,再切回系统偏好,状态就错乱。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
推荐解耦策略:
- 用 JS 读取
window.matchMedia('(prefers-color-scheme: dark)').matches仅作首次加载兜底,不监听后续变化 - 所有运行时切换,统一走
document.documentElement.setAttribute('data-bs-theme', ...)+.update() - CSS 规则全部基于
html[data-bs-theme="dark"]编写,不依赖媒体查询类名(如.dark) - 第三方库(如 React-Toastify)若自带主题检测,关掉它的自动模式,由你控制
data-bs-theme状态
记得声明 color-scheme: light dark
这个声明不控制你的 CSS,但它决定原生控件渲染方式:<input> 边框、<select> 下拉箭头、滚动条、<canvas> 默认边框等,在暗色系统下仍显示亮色,就是缺了它。
必须加在 :root 或 html 上:
html {
color-scheme: light dark;
}
否则即使 data-bs-theme="dark" 生效了,这些元素还是“违和”的亮色。
最易忽略的是:它必须和 data-bs-theme 同步设置——如果 JS 设置了暗色但忘了加这个声明,或者服务端没直出该样式,iOS Safari 就会固执地渲染亮色原生控件。

















