如果我告诉您,您可以使用单个属性值跨多个不同属性甚至跨多个CSS规则打开和关闭多个不同的值,会怎么样?
如果我告诉您,您只需调整一个自定义属性--is-raise,就可以将这个平面按钮变成一个有光泽的偏态按钮,这将一下子设置它的边框、背景图像、框和文本阴影,会怎么样?
这项技术的关键在于:有两个自定义属性值,它们几乎在任何地方都有效,只要有一个带回退的var()调用。
您可能已经知道的更明显的一个是初始值,它使属性只应用它的后备。因此,在以下代码中:
背景:var(--foo,线性渐变(白色,透明))HSL(2 2 10%~5 0%);边框:1px实心var(--foo,RGB(0 0 0/1));颜色:RGB(0 0 0 var(--foo,/.8));
我们可以将--foo设置为Initial以启用这些“后备”,并将这些值附加到属性值,添加渐变、设置边框颜色并一次性使文本颜色半透明。但是,当我们想要关闭这些值时,该怎么办呢?--foo(不会创建循环)的任何非初始值都应该有效。但是,有没有一个可以在所有三个声明中都起作用的呢?
事实证明,每个属性中都有一个var()引用,它在任何地方都适用,您可能永远也猜不到它是什么(除非您看过我的任何CSS变量演讲,并且对传递内容有很好的记忆力)。
这是空格!空格在自定义属性中非常重要。当你写下这样的东西时:
这不是无效的声明。这是一个声明,其中--foo的值实际上是一个空格字符。但是,空格在每个CSS属性值中都有效,只要允许使用var(),并且不会以任何方式影响其计算值。因此,我们只需将属性设置为一个空格(甚至是注释),而不会影响声明中存在的任何其他值。例如:
我们可以利用这一点将var()实质上转换为单子句if()函数,并根据单个自定义属性有条件地附加值。
作为概念证明,下面是使用此方法重构的两个按钮演示:
因为@Apply现在已经不存在了,所以我最初设想这是一个构建块,用于在浏览器中启用“Mixin”,这是一种可怕的技术攻击。但是,最大的限制是,这只适用于将值追加到现有值,或者将属性设置为整数值或初始值。没有办法说“如果设置了foo,背景应该是红色的,否则背景应该是白色的”。一些这样的条件句可以通过巧妙地使用追加来效仿,但不是大多数。
当然也有一定的可读性问题:--foo:;看起来是个错误,而且--foo:开头看起来很奇怪,除非您知道这项技术。然而,这可以很容易地通过评论来解决。或者甚至是常量:
:root{--on:初始;--off:;}button{--is-raise:var(--off);/*...*/}#foo{--is-raise:var(--on);}。
还要注意的是,最终我们会得到一个合适的if(),不需要如此可怕的黑客来模仿它,讨论已经在进行[w3c/csswg-drafts5009w3c/csswg-drafts4731]。