CSS自定义属性(变量)

2022-08-10 CSS 大约 6 分钟

一直以来我们都知道,CSS 中是没有变量而言的,要使用 CSS 变量,只能借助 SASS 或者 LESS 这类预编译器,但是新的草案发布之后,直接在 CSS 中定义和使用变量已经不再是幻想了。自定义属性(有时候也被称作CSS 变量或者级联变量)是由 CSS 作者定义的,它包含的值可以在整个文档中重复使用。由自定义属性标记设定值(比如: --main-color: black;),由var() (opens new window)函数来获取值(比如: color: var(--main-color))【CSS 变量模块 1 级草稿已发布 (opens new window),在2012年首次发布】

自定义属性语法:

  • 需要以--下划线开头。
  • 需要在选择器中定义。
element {
  --main-bg-color: brown;
}
1
2
3

var函数语法:

  • 使代码更易于阅读(更容易理解)
  • 使修改颜色值更加容易
// var 函数用于插入 CSS 变量的值。
var(name, value)
1
2
  • name: 变量名(以两条破折号开头)。
  • value:默认值(在未找到变量时使用)。

注意

变量名称必须以两个破折号(--)开头,且区分大小写!

相关信息

你可能会问,为什么选择两根连词线(--)表示变量?因为$foo被 Sass 用掉了,@foo被 Less 用掉了。为了不产生冲突,官方的 CSS 变量就改用两根连词线了。

# 基本用法

声明一个自定义属性,属性名需要以两个减号(--)开始,属性值则可以是任何有效的 CSS 值。和其他属性一样,自定义属性也是写在规则集之内的,如下:

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

相关信息

规则集所指定的选择器定义了自定义属性的可见作用域。通常的最佳实践是定义在根伪类 :root (opens new window) 下,这样就可以在 HTML 文档的任何地方访问到它了:

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

# 作用域

CSS 变量可以有全局或局部作用域。

  1. 全局变量可以在整个文档中进行访问/使用,而局部变量只能在声明它的选择器内部使用。
  2. 如需创建具有全局作用域的变量,请在 :root选择器中声明它。 :root 选择器匹配文档的根元素。
  3. 如需创建具有局部作用域的变量,请在将要使用它的选择器中声明它。

# 继承性

自定义属性会继承。这意味着如果在一个给定的元素上,没有为这个自定义属性设置值,在其父元素上的值会被使用。

<!DOCTYPE html>
<html lang="en">
<head>
    <style>
        .two {
            --test: 10px;
        }

        .three {
            --test: 2em;
        }

    </style>
</head>
<body>
<div class="one">
    <div class="two">
        <div class="three"></div>
        <div class="four"></div>
    </div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

在这个情况下, var(--test) 的结果分别是:

  • 对于元素 class="two"10px
  • 对于元素 class="three"2em
  • 对于元素 class="four"10px (继承自父属性)
  • 对于元素 class="one"非法值,会变成自定义属性的默认值

相关信息

  1. 自定义属性仅当需要的时候才会计算。
  2. 你不能为元素设置一个属性,然后让它从兄弟或旁支子孙规则上获取值。
  3. 属性仅用于匹配当前选择器及其子孙,这和通常的 CSS 是一样的。

# 默认值

var() (opens new window) 函数可以定义多个备用值(fallback value),当给定值未定义时将会用备用值替换。

相关信息

**备用值并不是用于实现浏览器兼容性的。**如果浏览器不支持 CSS 自定义属性,备用值也没什么用。它仅对支持 CSS 自定义属性的浏览器提供了一个备份机制,该机制仅当给定值未定义或是无效值的时候生效。

函数的第一个参数是自定义属性 (opens new window)的名称。如果提供了第二个参数,则表示备用值,当自定义属性 (opens new window)值无效时生效。第二个参数可以嵌套,但是不能继续平铺展开下去了,例如:

.two {
  /* 如果 --my-var 未定义,则为红色 */
  color: var(--my-var, red);
}

.three {
  /* 如果未定义 --my-var 和 --my-background 则为粉红色 */
  background-color: var(--my-var, var(--my-background, pink));
}

.three {
  /* 如果 --my-var, --my-background 都为无效, 则为粉红色 */
  background-color: var(--my-var, --my-background, pink);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

::: wanging

自定义属性 (opens new window)这些 fallback 语法允许使用逗号。比如 var(--foo, red, blue) 定义了一个 red, blue 的备用值——从第一个逗号到最后的全部内容,都会被作为备用值的一部分。

:::

# 有效性

传统的 CSS 概念里,有效性和属性是绑定的,这对自定义属性来说并不适用。当自定义属性值被解析,浏览器不知道它们什么时候会被使用,所以必须认为这些值都是有效的

不幸的是,即便这些值是有效的,但当通过 var() 函数调用时,它在特定上下文环境下也可能不会奏效。属性和自定义变量会导致无效的 CSS 语句,这引入了一个新的概念:计算时有效性

当浏览器遇到无效的 var() 时,会使用继承值或初始值代替。

<p>This paragraph is initial black.</p> 
1
:root { --text-color: 16px; }
p { color: blue; }
p { color: var(--text-color); }
1
2
3

在上面的例子中,浏览器将 --text-color 的值替换给了 var(--text-color),但是 16px 并不是 color (opens new window) 的合法属性值。该属性不会产生任何作用。浏览器会执行如下两个步骤:

  1. 检查属性 color 是否为继承属性。是,但是 <p> 没有任何父元素定义了 color 属性。转到下一步。
  2. 将该值设置为它的默认初始值,比如 black。

相关信息

当常规的 CSS 属性值中存在语法错误,该行则会被忽略。然而如果自定义属性的值无效,它并不会被忽略,从而会导致该值被覆盖为默认值。

# 修改 CSS 变量

在 JavaScript 中获取或者修改 CSS 变量和操作普通 CSS 属性是一样的。

// 获取一个 Dom 节点上的 CSS 变量
element.style.getPropertyValue("--my-var");

// 获取任意 Dom 节点上的 CSS 变量
getComputedStyle(element).getPropertyValue("--my-var");

// 修改一个 Dom 节点上的 CSS 变量
element.style.setProperty("--my-var", jsVar + 4);
1
2
3
4
5
6
7
8

# 浏览器支持

表格中的数字注明了完全支持该属性的首个浏览器版本。

函数 谷歌 ie 火狐 mac 欧鹏
var() 49.0 15.0 31.0 9.1 36.0

# 示例

<!DOCTYPE html>
<html lang="en">
<head>
    <style>

        :root {
            --color-fear: blue;
            --color-son: yellow;
        }

        .fear {
            width: 300px;
            height: 300px;
            background: var(--color-fear);
        }

        .son1 {
            --color-son2: red;
            width: 150px;
            height: 150px;
            background: var(--color-son);
        }

        .son2 {
            /* --color-son2: green; */
            width: 150px;
            height: 150px;
            /* 访问不到 son1中的 --color-son2 自定义属性 */
            background: var(--color-son2);
        }
    </style>
</head>
<body>
<div class="fear">
    <div class="son1"></div>
    <div class="son2"></div>
</div>
</body>
</html>
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
38
39
上次编辑于: 2023年7月4日 09:36