写 CSS 最烦的莫过于同一个颜色值复制粘贴十几遍:主色一改,得满文件找 #4a90d9 替换。CSS 变量(官方叫自定义属性)就是解决这个问题的:把值存起来起个名字,哪里要用就写哪里,改一处全站生效。

定义与使用:-- 和 var()

:root {
  --main-color: #4a90d9;   /* 定义变量,名字必须以 -- 开头 */
  --gap: 16px;
}

.card {
  color: var(--main-color);            /* 用 var() 取值 */
  border: 1px solid var(--main-color);
  padding: var(--gap);
  margin-bottom: var(--gap);
}

两个规矩要记住:变量名必须以 -- 开头,区分大小写;取值必须包在 var() 里。变量通常定义在 :root(文档根元素)上,这样全站都能用。之后想换主题色,只改 :root 里那一行就行。

变量会继承,所以能做局部换肤

变量定义在哪个元素上,它的所有后代都能读到。在某个容器上重新定义同名变量,容器内部就自动"换了肤":

.theme-dark {
  --bg: #222;
  --text: #eee;
}

.theme-dark p {
  background: var(--bg);
  color: var(--text);
}
<!-- 只有这个盒子里的内容是暗色,页面其他部分不受影响 -->
<div class="theme-dark">
  <p>我这块是暗色背景</p>
</div>

不用写任何额外的类,容器里所有用到 --bg 的元素自动跟着变。

缺省值和 calc 配合

.title {
  color: var(--missing, gray);   /* 变量没定义时,用逗号后面的兜底值 gray */
  margin: calc(var(--gap) * 2);  /* 变量可以进 calc 参与运算,结果是 32px */
}

写公共组件时给变量留个缺省值很实用:组件内部定好默认值,页面想定制就传变量,不传也不至于样式崩掉。

用 JS 读写变量

变量不只是 CSS 内部的事,JS 也能操作它:

const root = document.documentElement;

// 读取
const gap = getComputedStyle(root).getPropertyValue('--gap');
console.log(gap); // 输出: 16px(注意值前面可能带空格,用时记得 trim)

// 写入
root.style.setProperty('--gap', '24px');

setProperty 一执行,所有用到 --gap 的地方同时更新。主题切换、用户自选字号这类需求,改一个变量就够了,完全不用给每个元素挨个赋样式。

实战:一键切换明暗主题

把前面的知识串起来:

:root { --bg: #fff; --text: #222; }
body.dark { --bg: #1a1a1a; --text: #eee; }

body {
  background: var(--bg);
  color: var(--text);
}
document.querySelector('#themeBtn').addEventListener('click', () => {
  document.body.classList.toggle('dark');
});

按钮一点,body 挂上 dark 类,两个变量被重新定义,整站瞬间换肤。这就是变量继承 + 类名切换的经典组合,比写两套样式表省事得多。

小结

  • 变量以 -- 开头定义,var() 取值,通常写在 :root 上全站可用
  • 变量随元素继承,在容器上重定义就能实现局部换肤
  • var(--x, 默认值) 能兜底,calc() 里也能直接用变量
  • JS 用 getPropertyValue 读、setProperty 写,适合做动态主题

把重复出现的颜色、间距、圆角都提炼成变量,是 CSS 从"能写"到"好维护"的第一步。配合上一遍文章里的 Grid 或 Flex 布局用,改版效率会高一个档次。