CSS 变量(CSS 自定义属性)

这是 CSS 近十年最重要的特性之一。CSS 变量让你把颜色、间距、字号抽成"变量",一处定义全站复用,一改全改。它是构建可维护样式系统、实现主题切换(深色模式)的基础。学完这一篇,你写 CSS 的方式会彻底改变。

1. 基本语法

CSS 变量(官方叫"自定义属性",Custom Properties)的语法非常简单:

/* 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] 上重新定义变量,所有引用处自动跟随——这是当下做主题切换的标准方案。

两种切换方式:

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 变量有什么不一样?

结论:新项目优先用 CSS 变量。Sass/Less 还有用,但更多是因为嵌套、mixin、循环这些功能,而不是变量。

7. 实战建议

小结

CSS 变量是现代 CSS 的基石。语法极简:--name 定义、var(--name) 引用;写在 :root 全局可用、局部可覆盖;能被 JS 读写;配合媒体查询或 data 属性,深色模式等主题切换迎刃而解。学完这 12 篇,你已经具备了独立完成现代 CSS 开发的全部基础。下一步:多看优秀作品、多临摹、多实战,精进就在于"调"的过程。

← 上一篇 CSS 响应式设计

返回 CSS 教程目录

✈️💬