如果你有使用Sass或LESS,你可能已经在你的样式表中使用过变量了,也知道它们确实非常有用。如果你没有使用预处理器,那么你就可能会好奇这到底是怎么一回事,为什么变量会如此受欢迎,它们为何会这么有用。在这篇文章中,我们先大概讲一下为什么变量如此有用,然后再认识一下另一个特殊的变量:currentColor
。
变量的好处在哪?
CSS中的变量很有用,因为它们允许我们写更多DRY(不再自我重复,也就是不需要一直写重复内容的代码)代码。它们对于管理和维护大型项目也有非常好用,因为它们包含了大量重复的值。
变量最常见的用例之一是网站或应用程序中的颜色主题/方案。使用变量,在CSS文件中创建并管理颜色方案会容易得多。比如说,在CSS文件中,对于不同的属性,配色方案通常需要重复使用一些颜色值。如果你想要改变某个方案的主要颜色,你就需要在样式表内所有使用了这个颜色的地方进行更改。使用CSS变量,你可以在一个位置定义一个变量(例如,定义一个名为primary-color
的变量),赋给它一个颜色值,然后将这个变量作为一个值使用,你就可以在样式表中的任何地方使用它。然后,当你想要改变这个颜色的时候,你需要做的只是为这个变量分配一个不同的颜色值,这样,在样式表中所有使用了这个变量的地方都会自动地更新它们的颜色。
CSS2.1没有引入变量(不过,这也并不完全正确,正如你在这篇文章中看到的)。在2014年,和预处理器变量类似的本地CSS变量被引入了。这些变量可以说甚至比预处理器变量更好用。所有的CSS属性都可以接受一个CSS变量作为值。
除了新变量,CSS还配有一个关键字的值,几乎也相当于是一个变量:currentColor
关键字。
currentColor
关键字
这个currentColor
关键字就像是一个CSS变量,不同的是它有一个主要的限制:你只可以在能够接受<color>
值的地方使用它;如果该属性不能接受<color>
值,它也就不能接受currentColor
作为值。
以下是属性中能够接受currentColor
为值的使用示例:
box-shadow: inset 2px 2px 3px currentColor;background-color: currentColor; /* not a good idea! */background-image: linear-gradient(currentColor, transparent);
currentColor
和其它变量之间的另一个区别是,你没办法用给其它变量赋值的方法给它赋值。currentColor
的值是由当前元素使用的color
属性的计算值决定的。也就是说,currentColor
的值和当前color
属性的值是一样的,这也是currentColor
这个名字的由来。
所以,如果回到我们前面的例子中,currentColor
关键字把盒阴影的颜色设置为和div
一样的颜色,无论你给div
设置的是什么样的color
值。如果你没有设置任何的color
,它会继承div
的任何一个父元素的颜色。如果所有的父元素都没有color
,大多数浏览器会直接把它默认设置为黑色。
换句话说:currentColor
关键字就是用于设置元素的属性,然后该元素的子元素,就会继承该元素的color
属性设置的颜色值。因此,它其实就是作为一个inherit
值,允许那些不能通过属性或子元素继承的颜色进行继承。
这也意味着,对于已经继承了color
值的属性,currentColor
不会再被使用。
默认继承color
值的属性和元素
当一个元素有一个color
值,无论它是显示设置还是继承的,该元素的某些能够接受<color>
值的前景元素将会默认继承该color
值。
比如说,元素的边框是元素前景的一部分。因此,即使你没有指定边框的颜色,该边框都会得到和color
属性值一样的颜色。如果元素没有color
属性值,大多数浏览器通常会默认使用黑色。
这个示例中的边框颜色是紫色的:
.parent { color: purple;}.child { border: 5px solid; /* we didn’t specify the border color here */}
元素中将会得到/继承元素color
值的包括:
元素的文本内容——正是
color
属性使用的地方文本的轮廓
元素的边框
元素的盒阴影
img
的alt
文本。也就是,当无法显示图像时,代替图像出现的文本,会继承这个颜色值。列表项的小黑点和边框
一些浏览器(比如Chrome)水平线(
<hr>
)的边框颜色。(没有边框的话,颜色就不会受影响)。
如果你没有在某个元素的这些属性中显式地给它们设置颜色,它们就会默认继承元素的color
计算值。
下面的demo展示了上述元素属性的应用,它们继承页面中body
元素的color
值。改变body中的color
属性的值,可以看到这些元素的颜色也一起改变了。
此时,你可能会想:如果这么多的属性/元素都继承了color
值,currentColor
还可以怎么用呢?
使用currentColor
扩展颜色继承
在一些可以取color
值的地方,使用它是非常方便的。举一个可以使用currentColor
的示例,不能继承渐变的color
值的地方。CSS渐变图像,无论是线性渐变还是径向渐变,都不能继承颜色。通过使用currentColor
,你就可以做一个线性渐变作为背景图像。举个例子,通过调整来匹配你在其它某个地方指定的颜色作为一个主题的“主要颜色”。
background-image: linear-gradient(to bottom, currentColor, #fff);
这里有一个由Scott Kellum创建的示例,他进一步理解了这个概念,并为color
属性添加了一个动画效果。在color
属性值改变时,所有受到该color
影响的元素都会随之改变他们的颜色。查看一下Scott Kellum (@scottkellum)在CodePen上创建的示例currentColor。
这是一个使用currentColor
的非常棒的示例,特别是动画效果的部分。
不过,关于currentColor
的示例还有更多更多,我们一起来看看其中的一些。
currentColor
使用实例
currentColor
这个属性的主要意义是颜色级联,它能在各种地方派上用场。
currentColor
主题UI组件
在之前的demo中,我们可以看到currentColor
的一个非常实用(甚至是非常棒的,我必须说)的用例,是去年由Simon “Simurai”在CSSConfau上做的一个分享。这个分享的主要内容是:在UI组件中如何使用Flexbox、currentColor
和em
单位,来快速地直接在浏览器中编写整个Web Apps的样式。
为了演示currentColor
的可用性,Simon创建了一组UI元素,包括一些滑动条等。这些元素应用了相同的配色方案。对于滑动条的颜色和输入类型,他使用了currentColor
变量来迫使滑动条上滑块的背景颜色继承了color
属性,而下方的滑动框则不继承该颜色。
一个使用currentColor
来让滑动条的滑块应用color
属性的值的例子。(地址)
同样的,其它的UI组件也可以通过继承级联中某个你想要的位置的color
值来创建。由此,一个UI组件就创建好了。然后,利用级联和currentColor
,每次你都可以通过改变主要的color
值,然后得到一组新颜色的组件,这样几乎就把这整个过程给切实地自动化了。
如下面这个GIF图像所示。Simon使用了浏览器中的开发工具以及颜色拾取器来改变color
属性的值,然后得到了一个实时的组件颜色改变的预览。
Changing the value of the color
property will update the colors of all UI components that are inheriting this color, with the help of the currentColor
variable. (Source)
在currentColor
这个变量的帮助下,改变color
属性的值,所有继承了这个color
的UI组件的颜色也会跟着改变。(地址)
使用浏览器的devtools功能,你可以根据自己的喜好更改主题颜色,然后根据浏览器的样式,在你的文件夹中来保存你所做的更改。像了解关于它的一切,可以参阅Simon的分享还有他的博客文章。
使用currentColor
设置SVG样式
SVG是非常棒的东西,但是它们有一些样式比较奇特而且有局限性,这取决于你如何使用它们。这种情况下可以使用SVG的<use>
元素来重用部分SVG。
如果你对于<use>
元素不熟悉的话,你可以在这里查看它所有的相关资料。<use>
的意义是重用部分SVG,让我们在页面上的每个我们想要的位置放置这部分SVG的内容。通过use
重用SVG元素,我们实际上是创建了该元素的一个同步副本,这和图形编辑器中的“复制 粘贴”操作是类似的。但是这里的复制是同步的,即它的属性会随着初始内容的变化而变化。
<use>
元素在创建SVG sprites方面被大量使用。一个包含了所有图标的SVG元素被作为sprite使用,然后我们可以使用<use>
在页面上的任何位置插入sprite中的单个图标。你可以在这篇文章中阅读所有的关于SVG创建sprites的内容。
当一个元素被use
时,它内容的副本也会被克隆到一个shadow DOM(影子 DOM:一种依附于文档原有节点的子DOM)。也就是说这些内容不可以被CSS选中并编辑样式,和我们在常规的DOM中选择并编辑SVG元素甚至HTML元素样式的方法是不一样的。这是为什么像这样创建SVG样式的图标会受限制的一个原因。
使用currentColor
,我们可以绕过这个限制。通过设置currentColor
作为我们想要引入颜色值的属性的一个值,可以把我们在CSS中指定的颜色“leak”到使用了use
的SVG元素的内容中。
所以SVG图标的use
可以这样写:
<svg class="home-icon"> <use xlink:href="#home"></use></svg>
假设在sprites中定义的#home
图标包含了如下的内容:
<symbol id="home"> <rect id="bottom" fill="currentColor" ... /> <polygon id="roof" ... /></symbol>
我们可以把样式应用到图标上,然后把fill
的颜色级联到#roof
(一个没有fill属性的元素),这样color
值就会被#bottom
这个矩形的fill
属性继承。
.home-icon { fill: red; color: white;}
fill
的颜色将会从svg
到use
级联,然后到#roof
。color
值将会被作为#bottom
的填充颜色的值,因为currentColor
。
Fabrice Weinberg前阵子在他的CodePen博客上写了一篇关于这种技术的文章。
当你想要创建多组图标,而且每组图标是不同颜色时,这种技术是非常方便的。你需要做的只是根据情况改变CSS中color
和fill
的值。这种用法的示例在Fabrice的文章中有:
当然,在SVG中你可以在多个元素上使用currentColor
。但是,正如你注意到的,它只允许你改变SVG中的两种颜色。
如果你想更多地控制颜色,并指定更多能够引入到SVG中的颜色值,你需要更多的变量。这就是新的CSS变量规范派上用场的时候了。你可以点击这里阅读更多相关内容。
结束语
在前面的例子中,我们看到了如何在多个地方使用currentColor
,然后只在一个地方更改我们想要应用到这多个地方的颜色;而不是创建多个相同的颜色,然后全部更改它们。这有助于我们写更短一些的CSS,也为我们提供了某种形式的自动化,特别是像我们在Simon的分享中看到的UI组件。
使用CSS变量,你可以定义你自己的一组变量,然后在相似的或者多用例的情况下使用它们,因为新变量对于所有的CSS属性都是有效值,而不仅是那些只接受<color>
值的属性。处理SVG图标肯定会变得越来越容易,维护大型项目也是这样。同样的,如果你使用了预处理器,你就应该已经知道变量是多么有用了。
你可以想到更多使用currentColor
情况吗?如果有,请在下面的评论中分享吧~