Skip to main content

CSS 原生变量 (自定义属性)

CSS 变量(CSS variable)又叫做 CSS 自定义属性(CSS custom properties)

自定义属性-MDN(有时候也被称作 CSS 变量或者级联变量)是由 CSS 作者定义的,它包含的值可以在整个文档中重复使用。由自定义属性标记设定值(比如: --main-color: black;),由 var() 函数来获取值(比如: color: var(--main-color);)复杂的网站都会有大量的 CSS 代码,通常也会有许多重复的值。举个例子,同样一个颜色值可能在成千上百个地方被使用到,如果这个值发生了变化,需要全局搜索并且一个一个替换(很麻烦哎~)。自定义属性在某个地方存储一个值,然后在其他许多地方引用它。另一个好处是语义化的标识。比如,--main-text-color 会比 #00ff00 更易理解,尤其是这个颜色值在其他上下文中也被使用到。自定义属性受级联的约束,并从其父级继承其值。

如何声明#

声明一个 CSS 变量,属性名需要以两个减号(--)开始,属性值则可以是任何值,如下:

body {  --color-primary: red;}

在根伪类(全局作用域)中声明的变量可以在 HTML 文档的任何地方访问到它:

:root {  --color-primary: blue;}
  • 有效性: 变量可以赋予任何值, 如果属性值在引用处上下文环境中不是有效的 CSS 值, 不生效, 不阻塞;
  • 可以在内联样式中声明;
  • 相同的属性按声明顺序覆盖;

如何引用#

如开头所述,使用一个变量时用 var() 函数包裹以表示一个合法的属性值:

p {  color: var(--color-primary);}

var() 函数可以接受第二个参数, 表示变量的默认值。如果该变量不存在,就会使用这个默认值。

color: var(--color-primary, #888);

作用域和优先级#

同一个 CSS 变量,可以在多个选择器内声明。读取的时候,优先级最高的声明生效。这与 CSS 的"层叠"(cascade)规则是一致的。
回顾之前的 3 个声明:

:root {  --color-primary: blue;}body {  --color-primary: red;}p {  color: var(--color-primary);}

p 标签 color 的最终的表现为红色, 很明显, 这是传统的 css 属性继承逻辑。

JavaScript 中操作 CSS 变量#

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

// 获取一个 Dom 节点上的 CSS 变量 (经测试, 此方法似乎只能访问内联样式中声明的变量)element.style.getPropertyValue('--my-var')
// 获取任意 Dom 节点上的 CSS 变量 (此方法可以访问完整的层叠变量表)getComputedStyle(element).getPropertyValue('--my-var')
// 通过 document.documentElement 来访问根节点 `:root` 中的变量getComputedStyle(document.documentElement).getPropertyValue('--my-var')
// 修改一个 Dom 节点上的 CSS 变量element.style.setProperty('--my-var', jsVar + 4) // 会在内联样式中添加相关属性

无法通过 getComputedStyle(document.documentElement).setProperty 修改变量, 这将在运行时抛出一个 <...> property is read-only 的异常

相关 API: CSSStyleDeclaration.getPropertyValue [MDN]

兼容性#

  • IE 全系不支持, 对于放弃兼容 IE 的项目来说, 采用它是个不错的选择。
  • 不建议做兼容处理

图 1

参考#