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() 里运算符前后记得留空格。下一篇讲过渡和变换,给页面加上动效。