不可靠,因Chrome预加载不应用、Firefox延迟生效、Safari 12.1–13.x忽略;且独立CSS中变量无法注入:root,导致var()回退透明;所有主题变量须在主样式表中按先默认后覆盖顺序声明。

link media="(prefers-color-scheme: dark)" 为什么不可靠
直接用 看似简洁,但实际会出问题:Chrome 预加载但不应用,Firefox 可能延迟数秒才生效,Safari 12.1–13.x 根本不触发——它只在解析 HTML 时检查媒体查询,而此时系统偏好尚未稳定。更关键的是,dark.css 里定义的 CSS 变量(如 --bg)不会注入到 :root 作用域,后续 var(--bg) 仍 fallback 为 transparent 或浏览器默认值。
必须把暗色变量写进主 CSS,不能拆成独立文件
所有主题变量必须统一在主样式表中声明,顺序不能错:
-
:root块先定义全部默认值(哪怕只是--bg: #fff、--border: #ccc) -
@media (prefers-color-scheme: dark)块紧随其后,且只能写在顶层、不可嵌套 - 该媒体查询内只能覆盖已有变量,不能新增;漏掉任一被组件使用的变量(比如
--border-color),对应元素就会透明或失色 - 旧版 Safari 会直接忽略前置或嵌套的
@media块,所以别把它塞进@media (min-width: 768px)里面
Tailwind 用户别指望 dark: 自动加载外部 CSS
Tailwind 的 dark: 变体不是运行时逻辑,而是构建时生成的选择器(如 .dark .dark\:bg-gray-800)。它只响应 html 元素是否含 dark 类,和 link[media] 完全无关。如果你配了 darkMode: 'class' 却还引入 dark.css,反而可能因优先级冲突导致样式错乱。
正确做法是:
- 确保
tailwind.config.js中darkMode: 'class'已启用 - JS 初始化时操作
document.documentElement.classList.toggle('dark', ...) - 监听
window.matchMedia('(prefers-color-scheme: dark)')的change事件,动态更新类名 - 避免在同一个元素上混用
bg-white和dark:bg-gray-900以外的其他组合,否则特异性难控
手动切换时,CSS 文件拆分毫无意义
用户点按钮切深色,本质是状态覆盖系统偏好。此时你若依赖 link[media] 加载新 CSS,既无法保证加载时机,也无法让已渲染的 DOM 重新计算变量。真正起效的是:JS 修改 html 元素的 class 或 data-theme 属性 + 主样式表中对应选择器(如 html[data-theme="dark"] :root)重声明变量。
所谓“专属 CSS 文件”,只适合极简单场景(比如纯覆盖背景/文字色,且不涉及变量继承)。一旦项目用到 CSS 变量、第三方组件库或 SSR,就必须把所有主题逻辑收敛到单一样式表中,并在 内联初始化 JS 同步 class 与 localStorage,否则首屏必闪。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











