从下面的笔中可以看出,使用calc的css变量似乎并不尊重变量的级联性质:
:root {
--font-size-mult: 1;
--font-size: calc(var(--font-size-mult) * 16px);
}
* {
font-size: var(--font-size);
}
.large {
--font-size-mult: 2;
}
预期的行为是,具有.large类的文档的任何部分的字体大小将是常规16px的两倍。在这个例子中可以看到的是,如果我重新定义.large中的font-size变量,我会得到所需的行为,但这似乎是违反直觉的,因为--font-size的值已经是它需要的了。解析为正确的值。
在我测试的所有浏览器中似乎都是这种情况,因此它可能是规范的一部分,但它似乎不适合CSS的工作方式。我认为变量值将根据当前元素范围中其他变量的值计算,而不是根据变量定义的范围计算。
https://codepen.io/Smilebags/pen/MrRKMY
这是预期的行为吗?应该是这样的吗?
是的,这是预期的行为,实际上完全尊重自定义属性的级联性质。来自section 2.2 of the spec:
重要的是要注意,自定义属性在计算值时解析其值中的任何var()函数,该值在继承值之前发生。
这意味着在根元素上出现的自定义属性--font-size
的值实际上是calc(1 * 16px)
,而不是calc(var(--font-size-mult) * 16px)
,因为在为根元素计算var(--font-size-mult)
时会计算--font-size
表达式。
然后,这个计算值calc(1 * 16px)
由后代继承。您在任何后代上为--font-size-mult
设置的任何新值都将被忽略(除非存在对其的其他引用)。
这应该是预期的行为吗?好吧,我只能告诉你,规范声称这是防止祖先和后代之间的循环引用所必需的。在与上述句子相同的段落中:
通常,仅当同一元素上的多个自定义属性相互引用时,才会出现循环依赖关系;在元素树中较高元素上定义的自定义属性永远不会导致在元素树中较低元素上定义属性的循环引用。
最后,虽然Kriszta的答案演示了使用calc()
和自定义属性并考虑继承的正确方法,但您应该完全使用rem单元而不是自定义属性,因为该单元是专门针对此用例而制作的。
如果您将calc
移动到您调用vars的位置,而不是您声明它们的位置,它将更新。演示:
:root {
--font-size-mult: 1;
--font-size: 16px;
}
* {
font-size: calc(var(--font-size-mult) * var(--font-size));
}
.large {
--font-size-mult: 2;
}