六维教程

CSS 变量与 calc 函数

写样式时经常遇到一种尴尬,一个主题色在几十个地方重复出现,想换个颜色就得全文搜索替换。CSS 变量就是来解决这个问题的。它允许你给一个值起名字,然后到处引用它,改一处全站生效。

自定义属性,变量怎么定义

CSS 变量在规范里叫自定义属性。定义方式很简单,两个短横线开头,写在任何规则里:

:root {
  --main-color: #4a90d9;
}

:root 就是 html 根元素,把变量写在这里,全站都能用。使用时要通过 var() 函数取值:

.button {
  background: var(--main-color);
}

var() 还支持第二个参数做兜底值。变量没定义或者失效时,就用兜底值,页面不会崩:

.button {
  background: var(--main-color, #333);
}

全局变量,主题的基础

通常把三类东西放进 :root,主题色、间距、字号体系:

:root {
  --color-primary: #4a90d9;
  --color-text: #333;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --font-title: 1.5rem;
}

以后写样式就引用这些名字,比如 padding: var(–space-md)。想要整体调整间距,只改 :root 里一处,所有引用它的地方同步变化。

作用域,变量的覆盖能力

变量有个特别实用的特性,它会继承,而且可以在局部重新定义。同一个变量名,在不同选择器里可以有不同的值:

.card {
  --card-bg: #f0f0f0;
  background: var(--card-bg);
}

.card.dark {
  --card-bg: #222;  /* 局部覆盖,只影响这个组件 */
  color: #fff;
}

这个能力让组件化变得很舒服。写一个组件时先用变量占位,使用方只需要在外层重新定义同名变量,就能改变组件外观,完全不用动组件自己的样式。

calc 函数,让数值参与计算

布局里经常要算尺寸,比如”满宽减去 80px 的侧边栏”。CSS 本身不会算数,但 calc() 可以:

.main {
  width: calc(100% - 80px);
}

calc() 支持加减乘除,最大的特点是允许不同单位混合,这是其他写法做不到的,比如 100% 减 80px。注意两个语法坑。运算符前后必须有空格,否则整个表达式失效,calc(100% - 80px) 正确,calc(100%-80px) 直接报错。加减法优先级低,复杂的式子用括号明确顺序:

.box {
  width: calc((100% - 40px) / 2);
}

calc() 里也能用变量,两者配合非常常见:

.sidebar {
  width: calc(100% - var(--space-lg) * 2);
}

和 Sass 变量的区别

用过预处理器的同学会问,Sass 不是早就有变量了吗。区别在于编译时机。Sass 变量在编译成 CSS 时就固定了,是静态的。CSS 变量活在浏览器里,是运行时的,所以 JavaScript 可以随时改它:

// 通过 JS 修改变量,实现一键换肤
document.documentElement.style.setProperty('--color-primary', '#e74c3c');

这是纯 CSS 做不到的事,也是 CSS 变量最有魅力的地方。

完整示例,按钮主题

用变量做一套按钮,hover 时变深色:

:root {
  --btn-bg: #4a90d9;
  --btn-bg-hover: #3a78b8;
  --btn-radius: 6px;
}

.btn {
  padding: 10px 20px;
  border: none;
  border-radius: var(--btn-radius);
  background: var(--btn-bg);
  color: #fff;
}

.btn:hover {
  background: var(--btn-bg-hover);
}

换主题时只改 :root 里的三个值,所有按钮同步变化。如果再配合 JS 改变量,就能实现白天黑夜一键切换。

小结

CSS 变量解决了重复值的管理问题,calc() 解决了尺寸计算问题,两者还可以组合使用。记两个重点,变量在 :root 定义全局值、在局部选择器覆盖实现组件定制,calc() 里运算符前后记得留空格。下一篇讲过渡和变换,给页面加上动效。

上一篇
CSS 动画入门
下一篇
CSS 响应式设计入门