使用CSS变量

CSS 变量是由CSS作者定义的实体,其中包含要在整个文档中重复使用的特定值。使用自定义属性来设置变量名,并使用特定的 var() 来访问。(比如 color: var(–main-color);)。

类似于Sass等CSS预处理的变量,CSS变量在CSS3中可由浏览器直接实现

1.概念

CSS 变量当前有两种形式:

  • 变量,就是拥有合法标识符和合法的值。可以被使用在任意的地方。可以使用var()函数使用变量。例如:var(–example-variable)会返回–example-variable所对应的值
  • 自定义属性。这些属性使用–where的特殊格式作为名字。例如–example-variable: 20px;即使一个css声明语句。意思是将20px赋值给–example-varibale变量。

自定义属性和常规属性一样,作用在当前的层级,若没有定义,则从其父元素继承其值。

1.1 兼容性及处理

p-1.png

可见兼容要求略高,移动端如果不需要考虑ios9以下或Android5以下的机型可直接使用,当然还可以做兼容处理,如:

1
2
3
4
a {
color: #7F583F;
color: var(--primary);
}


1
2
3
4
5
6
7
@supports ( (--a: 0)) {
/* supported */
}

@supports ( not (--a: 0)) {
/* not supported */
}

或通过js在容器外层(html或body)增加一个className,根据className做hack处理。

1
2
3
4
5
6
const isSupported =
window.CSS &&
window.CSS.supports &&
window.CSS.supports('--a', 0);

document.body.classList.add('no-var')

2.基本用法

2.1 局部变量

声明一个局部变量:

1
2
3
element {
--main-bg-color: brown;
}

使用一个局部变量:

1
2
3
element {
background-color: var(--main-bg-color);
}

2.2 全局变量

依赖于:root选择器,其更多介绍可见mdn css/:root

声明一个 全局 CSS 变量:

1
2
3
4
:root {
--global-color: #666;
--pane-padding: 5px 42px;
}

使用一个 全局 CSS 变量:

1
2
3
.demo{
color: var(--global-color);
}

2.3 var()方法

CSS变量使用的完整语法为:

1
var( [, ]? )

用中文表示就是:var( <自定义属性名> [, <默认值 ]? )

如:

1
2
3
body {
background-color: var(--color, #cd0000); /* 结果为#cd0000 */
}

第二个参数不处理内部的逗号或空格,都视作参数的一部分。

1
2
var(--font-stack, "Roboto", "Helvetica");
var(--pad, 10px 15px 20px);

2.4 继承

自定义属性同样支持继承。一个元素上没有定义自定义属性,该自定义属性的值会继承其父元素。

如:

1
2
3
4
5
6
7
8
<div class="one">
<div class="two">
<div class="three">
</div>
<div class="four">
</div>
<div>
</div>

1
2
.two { --test: 10px; }
.three { --test: 2em; }

在这个例子中,var(–test)的结果是:

  • class=”two” 对应的节点: 10px
  • class=”three” 对应的节点: element: 2em
  • class=”four” 对应的节点: 10px (inherited from its parent)
  • class=”one” 对应的节点: 无效值, 即此属性值为未被自定义css变量覆盖的默认值

2.5 JavaScript 操作 CSS 变量

如:

1
2
3
4
5
6
7
8
9
// 设置变量
document.body.style.setProperty('--primary', '#7F583F');

// 读取变量
document.body.style.getPropertyValue('--primary').trim();
// '#7F583F'

// 删除变量
document.body.style.removeProperty('--primary');

*css与js通信的途径

对 CSS 无用的信息,也可以放入 CSS 变量。如

1
--foo: if(x > 5) this.width = 10;

上面代码中,–foo的值在 CSS 里面是无效语句,但是可以被 JavaScript 读取。这意味着,可以把样式设置写在 CSS 变量中,让 JavaScript 读取。

3 注意事项

3.1 命名规范

变量名不能包含$,[,^,(,%等字符,普通字符局限在只要是“数字[0-9]”“字母[a-zA-Z]”“下划线_”和“短横线-”这些组合,但是可以是中文,日文或者韩文

如:

1
2
3
4
body {
--深蓝: #369;
background-color: var(--深蓝);
}

3.2 CSS变量不合法的缺省特性

先看一个例子:

1
2
3
4
5
body {
--color: 20px;
background-color: #369;
background-color: var(--color, #cd0000);
}

请问此时body的background-color是?

。。。
思考10秒
。。。
。。。
公布结果:transparent

这是CSS变量非常有意思的一个点,对于CSS变量,只要语法是正确的,就算变量里面的值是个乱七八糟的东西,也是会作为正常的声明解析,如果发现变量值是不合法的,例如上面背景色显然不能是20px,则使用背景色的缺省值,也就是默认值transparent代替。

3.3 空格尾随特性

先看一个例子:

1
2
3
4
body {
--size: 20;
font-size: var(--size)px;
}

如果你以为是20px就太天真了,实际上,此处font-size:var(–size)px等同于font-size:20 px,注意,20后面有个空格,所以,这里的font-size使用的是元素默认的大小。因此,就不要妄图取消就使用一个数值来贯穿全场,还是使用稳妥的做法:

1
2
3
4
5
6
7
8
9
10
body {
--size: 20px;
font-size: var(--size);
}

/* 或者利用calc() */
body {
--size: 20;
font-size: calc(var(--size) * 1px);
}

3.4 相互传递特性

我们在CSS变量定义的时候可以直接引入其他变量给自己使用,如:

1
2
3
4
5
6
7
:root {
--green: #4CAF50;
--backgroundColor: var(--green);

--columns: 4;
--margins: calc(24px / var(--columns));
}

3.5 变量值只能用作属性值,不能用作属性名

1
2
3
4
5
.foo {
--side: margin-top;
/* 无效 */
var(--side): 20px;
}

对于复杂布局,CSS变量的这种相互传递和直接引用特性可以简化我们的代码和实现成本,尤其和动态布局在一起的时候,无论是CSS的响应式后者是JS驱动的布局变化。

4 demo

4.1 提取公共颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
:root {
--main-bg-color: brown;
}

.one {
color: white;
background-color: var(--main-bg-color);
margin: 10px;
width: 50px;
height: 50px;
display: inline-block;
}

.two {
color: white;
background-color: black;
margin: 10px;
width: 150px;
height: 70px;
display: inline-block;
}
.three {
color: white;
background-color: var(--main-bg-color);
margin: 10px;
width: 75px;
}
.four {
color: white;
background-color: var(--main-bg-color);
margin: 10px;
width: 100px;
}

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

4.2 响应式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
body {
--primary: #7F583F;
--secondary: #F7EFD2;
}

a {
color: var(--primary);
text-decoration-color: var(--secondary);
}

@media screen and (min-width: 768px) {
body {
--primary: #F7EFD2;
--secondary: #7F583F;
}
}

相关链接