CSS 变量(CSS 自定义属性)
这是 CSS 近十年最重要的特性之一。CSS 变量让你把颜色、间距、字号抽成"变量",一处定义全站复用,一改全改。它是构建可维护样式系统、实现主题切换(深色模式)的基础。学完这一篇,你写 CSS 的方式会彻底改变。
1. 基本语法
CSS 变量(官方叫"自定义属性",Custom Properties)的语法非常简单:
- 定义:以两个连字符开头,如
--primary。 - 引用:用
var(--primary)。
/* CSS 变量:以两个连字符开头定义,用 var() 引用 */
:root {
--primary: #4f8cff;
--text-color: #333;
--radius: 8px;
--gap: 16px;
}
/* 引用变量 */
.btn {
background: var(--primary);
color: #fff;
border-radius: var(--radius);
padding: var(--gap);
}
.article {
color: var(--text-color);
line-height: 1.6;
}这就是 CSS 变量。和 Sass/Less 的变量不同,CSS 变量是浏览器原生支持的——不需要编译,浏览器实时计算,还能被 JS 动态读写。
2. 作用域与继承
CSS 变量遵守普通 CSS 的层叠和继承规则。:root 选择器代表 html 元素,写在 :root 里的变量全站可用。也可以在任意选择器里局部定义——只对该元素及其后代生效。
/* :root 是全局作用域,变量全站可用 */
:root {
--primary: #4f8cff;
--padding: 16px;
}
/* 局部覆盖:在某个选择器里重定义,只对该元素及后代生效 */
.card {
--primary: #ff5722; /* 这张卡片的主色变橙 */
background: var(--primary);
}
.card .btn {
background: var(--primary); /* 这里也是橙色 */
}
/* 其他区域的 .btn 仍然是蓝色 */这个特性非常有用:你可以给某个区块定义不同的变量值,内部所有引用自动跟随变化——不需要为这个区块重写所有样式。比如让"危险区域"用红色系、"安全区域"用绿色系,只需改一个变量。
3. 回退值(fallback)
var() 可以接第二个参数——变量未定义时用的回退值。还能多层嵌套回退。
.box {
/* var() 的第二个参数是回退值 */
background: var(--bg, #fff); /* --bg 没定义就用 #fff */
/* 多重回退 */
color: var(--text, var(--default, black));
}
/* 检测浏览器是否支持 CSS 变量 */
@supports (--a: 0) {
/* 支持 CSS 变量时执行的样式 */
}
@supports not (--a: 0) {
/* 不支持的回退样式 */
}实际开发中,业务代码里很少用复杂回退——直接在 :root 把所有变量定义齐全更清晰。回退主要用于第三方库或不确定变量是否存在的场景。
4. 经典用法:深色模式
CSS 变量最广为人知的应用是主题切换。把所有颜色抽成变量,深色模式只需覆盖同名变量,业务代码一行都不用改。
/* 经典用法:深色模式切换 */
/* 浅色(默认) */
:root {
--bg: #ffffff;
--text: #333333;
--card-bg: #f5f5f5;
--border: #e0e0e0;
}
/* 深色:覆盖同名变量 */
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--text: #eeeeee;
--card-bg: #2a2a2a;
--border: #3a3a3a;
}
}
/* 或者用 data-theme 属性,JS 切换 */
[data-theme="dark"] {
--bg: #1a1a1a;
--text: #eeeeee;
}
/* 业务代码只用变量,不关心具体值 */
body {
background: var(--bg);
color: var(--text);
}
.card {
background: var(--card-bg);
border: 1px solid var(--border);
}关键认知:业务代码只用变量,不关心具体颜色值。切换主题时,只需在 :root 或 [data-theme] 上重新定义变量,所有引用处自动跟随——这是当下做主题切换的标准方案。
两种切换方式:
- 跟随系统:用
@media (prefers-color-scheme: dark),用户系统设了深色就自动切换。 - 手动开关:用
[data-theme="dark"],JS 给html加属性切换。两种可以结合——默认跟随系统,用户点了开关后用data-theme覆盖。
5. 用 JS 读写变量
CSS 变量最大的优势之一——它能被 JavaScript 实时读写。这让很多以前必须重渲染的场景变得简单:改一个变量,全站更新。
/* JS 读取和修改 CSS 变量 */
/* 读取 */
const primary = getComputedStyle(document.documentElement)
.getPropertyValue('--primary');
// 返回 " #4f8cff"(注意前面可能有空格)
/* 修改(写入) */
document.documentElement.style.setProperty('--primary', '#ff5722');
/* 切换深色模式的完整 JS */
const btn = document.querySelector('#theme-toggle');
btn.addEventListener('click', () => {
const current = document.documentElement.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
});典型应用:用户在颜色选择器里选了主色,JS 一行 setProperty('--primary', newColor),整站主色立刻变化。还有自定义字体大小、布局密度等用户偏好,都可以这样存。
6. CSS 变量 vs Sass/Less 变量
如果你用过 Sass 或 Less,可能会问:它们也有变量,CSS 变量有什么不一样?
- 编译时 vs 运行时:Sass 变量在编译时替换成具体值;CSS 变量在浏览器运行时实时计算。
- JS 可访问:Sass 变量 JS 看不到;CSS 变量可以 JS 读写。
- 继承与作用域:Sass 变量是静态的;CSS 变量遵守 DOM 层级,可以局部覆盖。
- 媒体查询响应:CSS 变量可以在不同断点改值,Sass 不行。
结论:新项目优先用 CSS 变量。Sass/Less 还有用,但更多是因为嵌套、mixin、循环这些功能,而不是变量。
7. 实战建议
- 所有可复用值都抽变量:颜色、间距、字号、圆角、阴影、动画时长。一改全改。
- 命名要有体系:推荐
--color-primary、--color-text、--space-md、--font-size-lg这种"分类-级别"命名,避免乱起名。 - 全局变量写在 :root:这是惯例,所有设计师/前端都这么写。
- 注意浏览器兼容:IE11 完全不支持 CSS 变量。现代项目(用户不用 IE)放心用,老项目兼容 IE 就别用。
- 不要过度:不是所有值都要抽变量。只有真正"会变、会复用"的值才抽。
小结
CSS 变量是现代 CSS 的基石。语法极简:--name 定义、var(--name) 引用;写在 :root 全局可用、局部可覆盖;能被 JS 读写;配合媒体查询或 data 属性,深色模式等主题切换迎刃而解。学完这 12 篇,你已经具备了独立完成现代 CSS 开发的全部基础。下一步:多看优秀作品、多临摹、多实战,精进就在于"调"的过程。
← 上一篇 CSS 响应式设计
返回 CSS 教程目录