必须用 :root 声明 css 变量,因其语义明确、作用域顶层且支持 js 动态修改;var() 必须带合法字面量 fallback(如 #333);命名需分层语义化(如 --color-primary-500);深色模式应结合 data-theme 类与完整 :root 声明。

必须用 :root 声明,别写在 html 或 body 里
浏览器把 :root 当作 CSS 作用域的顶层,所有后代元素都能继承这些变量,且支持被 JavaScript 动态修改。写成 html { --primary: #007bff; } 看似能用,但在 Shadow DOM、微前端子应用或某些框架(如 Vue 的 scoped style)中可能失效——因为 html 不是严格意义上的“根作用域”。更关键的是,:root 语义明确、优先级稳定,不会被局部选择器意外覆盖。
var() 必须带字面量 fallback,否则文字可能变透明
var(--color-text) 在变量未定义时不会报错,而是回退到该属性的初始值或继承值:Chrome 可能取 inherit,Firefox 可能渲染为 transparent,结果就是文字突然消失。这不是 bug,是规范行为。
- 正确写法:
color: var(--color-text, #333);✅ - 错误写法:
color: var(--color-text, unset);❌(unset不是合法颜色值) - fallback 不是“兜底给旧浏览器”,而是“变量值无效时强制生效”
命名要分层语义化,别用组件名或具体色值
变量名不是越短越好,而是要扛得住半年后的维护。用 --header-bg 或 --btn-primary-color 这类绑定组件的命名,换一个 UI 结构,变量就废了;用 --blue-500 这类带色值的命名,换品牌色就得全量搜索替换。
- 推荐结构:
--color-primary-500(基础值) +--color-text-primary(用途映射) - 禁用命名:
--primary-blue、--card-bg、$accent - 值推荐用十六进制或
hsl(),别用命名色(如blue),后者无法被 JS 读取计算,也不利于深色模式切换
深色模式切换别只靠 @media (prefers-color-scheme: dark)
纯媒体查询适合系统级自动切换,但用户手动选“深色/浅色/蓝调/墨绿”时就会失效。更可靠的方式是用 data-theme 类配合批量注入:
- 默认主题必须在
:root中完整声明,不能只在[data-theme="dark"]里补缺 - JS 切换时用
Object.entries(theme).forEach(([k, v]) => doc.documentElement.style.setProperty(k, v)),避免漏项 - 注意 Safari 旧版本对嵌套
var()(如--color-text: var(--color-primary))支持不稳定,建议扁平化声明
真正难的不是定义变量,而是让每个 var() 都出现在该出现的地方——比如按钮的 :hover、:focus、禁用态,漏掉一个,主题切换就露馅。这没法靠工具自动发现,得靠代码审查和组件样式清单兜底。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











