前端开发者学堂 - fedev.cn

currentColor与CSS自定义属性之间的差异

发布于 大漠

变量对于CSS而言是这两年大家关注的一个话题。对于变量而言,最早是出于CSS的一些处理器语言当中,比如Sass、LESS之类的。随着CSS的发展,变量的概念也被引入到CSS中。时至今日,在CSS中的变量不被称作变量,而被称为CSS自定义属性。该特性让我们维护CSS、编写CSS变得更易。而事实上呢?在CSS最早的变量之一是currentColor。该特性也可以更好的帮助我们编写CSS和扩展CSS。那么今天我们来开另一个话题,currentColor和CSS自定义属性又有何差异呢?接下来的内容,我们就来一起探讨这方面的细节。

currentColor和自定义属性之间还是存在一些有趣的区别。这两个都是CSS中动态属性的例子,但是它们的解析方式在一些非常重要的方面还是有所不同的。至于为何不同,接下来的内容将向大家揭开。

currentColor

简单的回忆一下CSS中的变量关键词currentColor。这个关键词就像是一个CSS变量,不同的是它有一个主要的限制:

只可以在接受<color>值的地方使用它;如果该属性不能接受<color>值,它就不能接受currentColor作为值。

在CSS中,能接受<color>值的属性比较多,比如border-colorbackground-colorbox-shadowtext-shadowoutline以及CSS渐变属性等。如果我们希望元素的边框、阴影、背景等颜色和color同步,那么我们就可以使用currentColor。比如:

box-shadow: inset 2px 2px 3px currentColor;
background-color: currentColor;
border-color: currentColor;
background-image: linear-gradient(to bottom, currentColor, rgba(0,0,0,0));

当然,currentColor和其它变量之间的另一个区别是,你没办法用给其它变量赋值的方法给它赋值。currentColor的值是由当前元素使用的color属性的计算值决定的。比如下图所录制的效果:

正如上图所示,在currentColor变量的帮助下,改为color属性的值,所有继承了color的UI组件的颜色也会随着改变。

有关于currentColor更详细的介绍,可以阅读早前整理的《使用CSS的currentColor变量扩展颜色级联》一文。

CSS自定义属性

了解了currentColor之后,再来简单的回忆一下CSS中的自定义属性。CSS自定义属性最早的思路来源于CSS处理器中的变量,其最早也常被称为CSS的变量,但事实上他和变量还是有很大的差异的,所以后面为了更为统一化,将这一特性称之为CSS自定义属性。更为值得庆幸的是,该特性被纳入到了W3C规范中,成为一个独立的模块,即:CSS Custom Properties for Cascading Variables Module Level 1

CSS自定义的属性使用其实非常的简单,他也类似于CSS其他处理器一样,需要先声明,然后在调用。声明CSS自定义属性非常的简单,使用--为前缀,带一变量名和变量值,这样就声明了一个自定义属性,比如:

:root {
    --color: red;
}

在根元素:root中声明了一个--color自定义属性,该属性被称为全局性的,当然我们也可以在某个CSS规则块中声明:

.box {
    --color: blue;
}

同样是声明了一个--color属性,只不过这个是属于局部的。声明之后,我们在调用的时候,可以使用var()函数来调用,比如:

.box {
    color: var(--color);
}

CSS自定义属性,使用就是这么的简单。但自定义属性中还有很多很有意思的东西。只不过不在这里进行阐述,如果感兴趣的话,可以阅读小站上有关于CSS自定义属性相关的文章

currentColor和CSS自定义属性之间的差异

通过前面的内容,我们简单的了解了CSS中currentColor和CSS自定义属性在CSS中所起的作用。接下来我们回到今天真正的主题上来。这两者之间有何差异。

假设我们有一个这样的场景,我们希望标题的边框和正文的颜色应用同一种颜色。如下图所示:

事实上实现上面的效果并不是难事。难得是我们如何以最少的代码量和最简易方式来实现。特别是面对换肤的需求时,我们如何可以最简易地做到这一点。比如说,通过一个类来理想的设置皮肤效果。

假设我们希望改变的body的文本颜色 而不仅仅是段落的颜色,因此在容器元素上设置color。刚开始这样设置是有意义的,因为这样做允许容器内的所有元素都会继承主题的颜色,然后我们可以将标题的颜色重置为black

但我们有一个前提性的需求,只想在一个地方设置颜色,而标题上的border-color要继承这个颜色,目的是希望标题边框的颜色和主体文本颜色一样。或许你会想到CSS中的继承关键词inherit。但事实上呢?像下面这样设置,并未达到我们的需求:

body {
    color: red;
}

h3 {
    color: #000;
    border-color: inherit;
}

边框的颜色也变成了#000,如下图所示:

注意,虽然在border-color属性中显式的设置了值为inherit关键词,其实得到的效果和在border属性中不显式设置border-color得到的效果是一样的:

border: 3px double;

这是因为,在border属性中,如果未显式的设置border-color的值时,边框的颜色会继承文本color的值。

为什么会这样呢?我们来简单的说一下其中的原理。

由于body中(或者你为一个主题设置了一个全局的类,比如theme这样的类)只设置了color的值为red,并未显式设置border-color的值。这也造成border-color的值使用的是默认值,而border-color的默认值是currentColor。也就是说,基于此例的上下文,currentColor的值是red,这也是预期想要继承的值。

既然如此,为什么效果和我们所预期的不一样呢?这之间倒底是发生了什么呢?这主要是因为我们在h3标题中重置了color的值为#000,而border-color仍然从父元素继承值,但结果是,当我们继承currentColor时,并未从父元素中检索该属性的解析值,相反,我们inherit关键词本身,计算值将在本地上下文中解析。所以造成上面示例中的border-color#000。简单的来看一下这样的过程:

  • body元素中,border-color采用的是默认值currentColor,即red(在本例中)
  • h3中,显式的设置了border-color值为关键词inherit,即继承了父元素border-color的值,也就是继承了currentColor的值

根据前面currentColor的内容可得知,他的值取决于元素自身的color值,而上例中,为了重置标题的文本颜色为black,所以显式的重置了该元素的color值为black,这样也就直接影响了currentColor的值,因此最终大家看到的效果就是标题的边框颜色也变成了黑色

有关于inherit更为深入的介绍,建议阅读前面整理的《图解CSS:CSS层叠和继承》和《管理CSS层叠》。

上面也提到了,h3显式设置了border-color的值为inherit,继承了border-color的值currentColor,而currentColor取决于自身元素的color值。如此一来,要解决这个问题就显得非常的简单了,我们只需要在body元素上显式的设置border-colorred即可:

body {
    color: red;
    border-color: red;
}

h3 {
    color: black;
    border-color: inherit
}

现在h3border-color不再继承动态属性currentColor,其颜色按预期的继承了red。得到了我们想要的效果:

我们达到了预期的目标,只需要在body上设置颜色即可。如果我们现在更换主题颜色,那么只需要在body上重置即可,如下图所示:

其实这已经是我们想要的了,但事实上,我们还有更为简易的方式来帮助我们维护。那就是借助CSS自定义属性。尽管CSS自定义属性也是动态的,但在相同情况之下,CSS自定义属性不会像currentColor那样工作。比如说,我们使用CSS自定义属性来修改上面的示例:

body {
    --color: red;
    color: var(--color);
    border-color: var(--color);
}

h3 {
    --color: black;
    color: var(--color);
    border-color: inherit;
}

在这种情况之下,h3border-color继承了父元素body的自定义属性--color。但是,即使h3color的值是本地的自定义属性--color(局部变量),它的border-color也不会像currentColor那样使用这个本地声明的自定义属性值。

继承自定义属性设置的值始终与父属性解析的值相匹配

注意,本例中的color属性将取局部的值,因为它不是继承的。

这里的关键区别是:currentColor关键词不是在计算值时解析,而是对本地color属性的使用值的引用。

总结

一开始,我一直以为currentColor关键词和CSS自定义属性非常的相似,都是相似的动态属性。然而事实证明,有一些根本的区别是我们应该要意识到的。比如文章中所举例的示例,再次强调了CSS自定义属性和currentColor之间是有所不同的。air max 90 essential release