现在业务中经常会使用一些 CSS 的预处理器或后处理器,他们极大的方便了开发过程中的 CSS 片段复用。但其实 CSS 原生也做出了一些改变,在兼容性没有那么苛刻的情况下, 可以尝试使用。本文就是我对 CSS 原生变量的探讨和认知。

简介

跟 JS 中的变量一样,目的都是为了复用并且减少 CSS 值的冗余。

javascript中在html中显示变量 html中的变量_CSS

比如这里的 1,2,3 处我们可以这么定义

.tabTitle {
color: #007fff;
}
.tabSubtitle {
color: #007fff;
}
.hot {
color: #007fff;
}

复制代码

都是使用的相同颜色,这么写没大问题,但是如果有一天设计师让我们修改这个颜色的时候就需要修改所有的地方,变量的方便就体现出来了。

:root {
--main-color: #007fff;
}
.tabTitle {
color: var(--main-color);
}
.tabSubtitle {
color: var(--main-color);
}
.hot {
color: var(--main-color);
}

复制代码

这就是变量的基本用法 :root是定义变量作用域(scope)为根作用域,其含义为标签下的作用域,相当于 js 中的全局作用域。

变量名称

变量名只能数字,字母以及_或-,其余符号均为非法。空格都是不允许的

/*合法*/
:root {
--main_color: #007fff;
--_main-color: #007fff;
--1_main_color: #007fff;
}
/*非法*/
:root {
--main color: #007fff;
--_main#$%^color: #007fff;
}

复制代码

作用域

任意元素均可作为 CSS 变量的作用域;

:root {
--main-color: #007fff;
}
.title {
--main-color: red;
color: var(--main-color);
}

复制代码

fallback

这里的备选并不是指如果浏览器不支持 CSS 变量而使用的备选值。

.title {
color: var(--main-color, green);
}

复制代码

这里是如果main-color没有被定义的话, 则使用green的 fallback。而且该值可以任意嵌套

.title {
color: var(--main-color, var(--sub-color, green));
}

复制代码

如果没有定义值, 也没有备选值, 那么该属性将会被忽略。

典型 cases

控制一个组件的大小

javascript中在html中显示变量 html中的变量_作用域_02

假设有三个不同大小的按钮:small, medium, large


primary



primary


primary



复制代码

css对应为

.button {

--unit: 1em;

padding: var(--unit)

}

.button--small {

--unit: 0.5em;

}

.button--large {

--unit: 1.5em;

}

复制代码

HSL 颜色

HSL 表示 hue(色值),Saturation(饱和度), brightness(亮度)hue 决定了颜色,satuation和 brightness 决定这个颜色的亮和暗。

如果要实现一个 button 在 hover 的时候亮度减少为原来的 1/3,除了重写 background-color 之外,可以使用 css 变量更优雅的处理。

:root {
--hue: 221;
--sat: 71%;
--bri: 48%;
}
.button {
background-color: hsl(var(--hue), var(--sat), var(--bri));
transation: background-color .3s ease-in-out;
}
.button:hover {
--bri: 33%
}

复制代码

按比例 resize
css 使用变量可以很轻易的实现。
.icon {
--size: 22px;
width: var(--size);
height: var(--size);
}

复制代码

add

复制代码

document.querySelector('.add').addEventListener('click', () => {
const iconDom = document.querySelector('.icon');
currentSize = parseInt(getComputedStyle(iconDom).getPropertyValue('--size'))
iconDom.style.setProperty('--size', currentSize * 2 + 'px')
})

复制代码

demo

结合 react 的 jsx 的话威力更大,可以感受一下这个作用域的意义。

复制代码

如果是有一定宽高比,那么引入一个 --ratio 即可。

储存完整值与部分值

CSS 渐变

:root {
--gradient: linear-gradient(150deg, #235ad1, #23d1a8)
--angle: 150deg;
}
.total {
background-image: var(--gradient)
}
.angle {
background-image: linear-gradient(var(--angle, 150deg), #235ad1, #23d1a8);
}
.angle:hover {
--angle: 0deg;
}

复制代码

切换黑暗和明亮模式

:root {
--text-color: #434343;
--border-color: #d2d2d2;
--main-bg-color: #fff;
--action-bg-color: #f9f7f7;
}
.dark-mode {
--text-color: #e9e9e9;
--border-color: #434343;
--main-bg-color: #434343;
--action-bg-color: #363636;
}

复制代码

储存多个值

在多值属性的时候,如果只有部分改变其余部分保持一致的时候可以提取保持一致部分为变量。类似的有 rgba, hsl, background 等等任意多值属性, 用逗号隔开即可。

:root {
--main-color: 35, 90, 209
}
.title {
color: rgba(var(--main-color), 0.75)
}

复制代码

与动画结合

可以很方便的复用animation

@keyframes breath {
from {
transform: scale(var(--scaleStart));
}
to {
transform: scale(var(--scaleEnd));
}
}
.walk {
--scaleStart: 0.3;
--scaleEnd: 1.7;
animation: breath 2s alternate infinite;
}
.run {
--scaleStart: 0.8;
--scaleEnd: 1.2;
animation: breath 0.5s alternate infinite;
}

复制代码

注意有个问题,类似下面的场景是没有动画的

.box {
transform: translate(var(--offset, 0));
}
.box-1 {
animation: offsetAnimation .3s alternate infinite;
}
@keyframes offsetAnimation {
from {
--offset: 0;
}
to {
--offset: 100px;
}
}

复制代码

不过 chrome, ff,safari 现在支持属性的定义@property语法,在元素上注册自定义属性,可参考地址

@property --offset {
syntax: "";
inherits: true;
initial-value: 0;
}

复制代码