引言
众所周之,CSS 的维护一直是件不易的事情,特别是在构建大型 Web 站点或 Web 应用程序时,如果是多人协作的话难度更大。另外,由于 CSS 语言是一种声明式语言,而且不像其他语言有变量、条件和逻辑等特性,一直生存在程序语言鄙视链的最底层。也因为这个原因,社区中有了各种 CSS 处理器语言,比如 Sass、LESS 和 Stylus 等。这些处理器语言引入了一些类似其他程序语言的特性,比如变量、运算符和逻辑运算等。
虽然 CSS 处理器给编写和维护 CSS 带来了一些便利,但还是需要额外的编译。不过处理器中的变量着实为我们带来很大的优势,也正因为如此,社区开始将 CSS 处理器中的变量引入到原生 CSS 中,经过多年的推进和演变才有了今天的 CSS 自定义属性。
一、CSS 自定义属性简介
所谓自定义属性,就是 CSS 作者(CSSer)自己定义的属性,这些属性统称为自定义属性,允许作者自由的选择名称,自由的为名称属性分配任意值。这些属性能够提供给 var()函数使用,被 var()函数引用的自定义属性又常被称为变量。
这样一来,CSSer 声明的这些自由属性就有了两个名称:自定义属性 和 变量:
自定义属性 :使用 –( 代表任意声明的名称)声明的特殊格式作为名称,该名称被称为自定义属性,同时可以给自定义属性赋予任何值。比如 –color: #fff。
变量 :CSS 的 var() 函数引用的自定义属性被称为变量。var()会返回自定义属性所对应的值,同时可以被运用于相应的 CSS 属性。对应的即是 CSS 规则中的属性值。
用一张图来描述他们之间的关系:
二、CSS 自定义属性的作用
当我们构建大型 Web 网站或 Web 应用时,使用的 CSS 数量是非常庞大的,并且在很多场合有着大量的重复使用。就拿网站的配色方案来举例,一些颜色在 CSS 文件中会出现很多次,并被重复使用。当你修改配色方案时,不论是调整某个颜色或完全修改整个配色,都会是一个复杂的问题。如果单纯的依赖全局的查找替换是远远不够,这样的操作难免会出错。
如果使用了 CSS 的框架,这种情况会变得尤其糟糕,此时如果要修改颜色,则需要对框架本身进行修改。虽然这些框架都有可能引入了 Sass 这样的 CSS 处理器帮助我们减少了出错的机会,提高了可维护性的能力,但这种通过添加额外步骤的方式(需要做编译处理),可能会增加系统的复杂性。
CSS 自定义属性(CSS 变量)的出现,为我们带来了一些 CSS 处理器的便利,并且不需要额外的编译。在 CSS 中使用 CSS 自定义属性的好处和在编写语言中使用变量的好处没有特别的不同之处。W3C 规范上有过这样的一段描述:
使用 CSS 自定义属性使得大文件更易于阅读,因为看起来很随意的值有了一个提示信息的名字,并且编辑这些文件更加简单,更不易于出错。因为你只需要在自定义属性处修改一次,这个修改就会应用到使用该自定义属性的任何地方。
简单地说,CSS 自定义属性除了提供了更灵活的设置、引用和修改的便利性之外,还具有较强的语义化(这需要你对语义化有足够强的意识,比如 primary 这样的名称总是要比 red 这样的名称来得有意义)。这些语义化信息让你的 CSS 文件变得易读和理解。
为此,可读性和可维护性是 CSS 自定义属性最大的优势。并且,它让我们可以在 CSS 中使用原生的变量,而不再需要借助于类似 Sass 这样的 CSS 处理器。
三、CSS 自定义属性语法
3.1 自定义属性的声明
CSS 自定义属性和常规 CSS 属性的用法是一样的。把它们当作动态属性会比变量更好。这意味着它们只能在声明块中使用。也就是说,自定义属性和选择器是强绑定的。可以是任何有效的选择器。
如果已声明的 CSS 自定义属性未被任何属性调用的话,将不会产生任何的效果。只会是一段字符串停留在你的样式文件中。
声明自定义属性的时候,自定义属性名前面要加两根连词线(–)。
body {
--foo: #7F583F;
--bar: #F7EFD2;
}
CSS 自定义属性的命名规则比较松散,可以是任何有效的字符,比如中文、大写字母、驼峰命名、中距线、emoji 和 HTML 实体等等:
自定义属性名大小写敏感,–color 和 –COLOR 是两个不同的自定义属性。
3.2 var() 函数
var()函数用于读取变量, 将变量当作 var()函数的第一个参数传进去。
a {color: var(--foo);
text-decoration-color: var(--bar);
}
var()函数还可以使用第二个参数,表示自定义属性的默认值。如果该自定义属性不存在,就会使用这个默认值。
color: var(--foo, #7F583F);
var() 的第二个参数不处理内部的逗号或空格,都视作参数的一部分。
var(--font-stack, "Roboto", "Helvetica");
var(--pad, 10px 15px 20px);
var()函数还可以用在自定义属性的声明。
:root {
--primary-color: red;
--logo-text: var(--primary-color);
}
var()函数可以代替元素中任何属性中的值的任何部分。不过 var()函数不能作为属性名、选择器或者其他除了属性值之外的值。
.foo {
--side: margin-top;
/* 无效 */
var(--side): 20px;
}
四、CSS 自定义属性的使用
4.1 CSS 自定义属性命名
CSS 自定义属性的命名规则比较松散,可以是任何有效的字符,比如中文、大写字母、驼峰命名、中距线、emoji 和 HTML 实体等等:
4.2 CSS 自定义属性和 CSS 属性工作原理完全相同
CSS 自定义属性可以在任何元素、选择器,甚至是伪元素上声明的普通属性。他的使用和 CSS 属性的使用是相同的,原理也是相同的:
:root {--font-size: 1em;}
p {font-size: var(--font-size);
}
section::after {font-size:1.5em;}
4.3 CSS 自定义属性和 CSS 属性一样具有继承和级联特性
举个例子,每个 Web 应用都会有自己的下色系,就拿 Bootstrap 这个 CSS 框架的色系来说吧,它的主色系是 –primary: #007bff,该色会用于多个地方,比如:
:root{--primary: #007bff;}
// Button 组件
.btn-primary {background-color: var(--primary);
border-color: var(--primary);
}
// Badge 组件
.badge-primary {background-color: var(--primary);
border-color: var(--primary);
}
// Dropdowns 组件
.dropdown-primary {background-color: var(--primary);
border-color: var(--primary);
}
// Pagination 组件
.page-link {color: var(--primary);
}
// Progress 组件
.progress-bar {background-color: var(--primary);
}
这样,当我们想换换色系的时候,只需要调整:root 中的 –primary 的值即可。
自定义属性的级联写法如下:
:root {--color: #333;}
.card {color: var(--card);
&:nth-child(2) {--color: #2196F3;}
&:nth-child(3) {--color: #f321ab;}
}
对于自定义属性的继承,举个例子如下:
<!-- HTML -->
<p> 我是什么颜色?</p>
<div> 我又是什么颜色?</div>
<div id="alert">
我是什么颜色?
<p> 我又是什么颜色?</p>
</div>
// CSS
:root {--color: #333;}
div {--color: #2196F3;}
#alert {--color: #f321ab;}
4.4 CSS 自定义属性可以在行内 style 属性中使用
CSS 自定义属性和 CSS 属性一样,可以在元素的 style 属性中使用 CSS 自定义属性。
<!-- HTML -->
<button style="--color: blue">Click Me</button>
// CSS
button {border: 1px solid var(--color);
}
button:hover {background-color: var(--color);
}
五、浏览器的支持性
CSS 的自定义属性是 CSS 的一个重要的新功能,到目前为止所有的现代浏览器中都对 CSS 自定义属性做了良好的支持,这将使得原生 CSS 从此变得更加强大。
参考文章:
图解 CSS:CSS 自定义属性
CSS 变量教程 – 阮一峰