【问题标题】:Errors in CSS variables and calculations: How can I get error output?CSS 变量和计算中的错误:如何获得错误输出?
【发布时间】:2020-07-30 03:54:24
【问题描述】:

我开始使用 CSS 变量来尝试制作模块化尺寸比例。但我很快就遇到了忽略 CSS 值的问题,但我没有看到任何关于错误的迹象。

让我们看看问题的最小再现:

:root {
  --ratio: 1.25;
  --font-size-medium-heading: calc(var(--ratio) * 1rem);
  --font-size-large-heading: calc(var(--font-medium-heading) * var(--ratio)); /* note the typo in the var */
}

h1 {
  font-size: var(--font-size-large-heading);
}

我故意打错字看看会发生什么(我在变量名中省略了-size)。由于我的标题变小了,我尝试查询我的新 CSS 变量的值:

getComputedStyle(document.documentElement).getPropertyValue('--font-size-large-heading') === ''

它返回一个空字符串。

让我们前往 Chrome 的样式检查器,看看我是否收到警告标志⚠️:

MDN 建议使用 CSS 验证器。所以让我们试试这个:https://jigsaw.w3.org/css-validator/validator

我的猜测是这个验证器并不是最新的(如果有人还在使用它的话)。

更新 我知道根据规范它是一个有效的语句,但它的计算时间值是无效的。我想知道这些,因为它只是将真正的问题隐藏在一个非常常见的错误中(如果你曾经花了一天时间发现 Angular 在模板中期望 "'thing'" 而不是 "thing",你就会明白如何bad 没有关于无效值的输出)。

有没有办法获得关于计算时间无效 CSS vars 和 calc 值的错误输出?

【问题讨论】:

  • 您的代码没有任何问题,一切都有效。您正在使用一个名为 --font-medium-heading 的变量,即使您没有定义它也是有效的。您将仅在计算时间获得无效值,或者您稍后将在代码中定义它
  • @TemaniAfif 请参阅下面我对 Zohir Salak 回答的评论;我不介意它是否有效,我介意我找不到任何东西告诉我一个值被忽略了。这是十亿美元的错误。
  • 但它的计算时间值无效。 --> 你没有计算值,因为你还没有使用变量

标签: css error-handling css-variables css-calc


【解决方案1】:

首先是spec

如果一个属性包含一个或多个var() 函数,并且这些函数在语法上是有效的,则必须假定整个属性的语法在解析时是有效的。在 var() 函数被替换之后,它只在计算值时进行语法检查。

这就是为什么您在 chrome devtool 中看不到黄色三角形的原因,因为从语法上讲它是有效的。


spec关注第四条规则

  1. 否则,包含 var() 函数的属性在计算值时无效

还有

如果声明包含引用具有 保证无效值的自定义属性的 var(),则声明可能在计算值时无效强>

代码中的第三行包含一个 var(),它引用了一个具有 保证无效值

的 css 变量

为什么?

自定义属性的初始值为guaranteed-invalid value。正如§ 3 Using Cascading Variables: the var() notation 中定义的那样,使用 var() 将自定义属性替换为 this 作为其值会使引用它的属性在计算值时无效。

一个不存在的 css 变量基本上创建了它,它的初始值是保证无效值。


计算的初始值是多少?

此值序列化为空字符串,但实际上将空值写入自定义属性(如--foo: ;)是有效(空)值,而不是保证无效值。如果出于某种原因,想要手动将变量重置为保证无效值,则使用关键字 initial 即可。

这就是getComputedStyle(document.documentElement).getPropertyValue('--font-size-large-heading')返回“空字符串”的原因(保证无效值)

【讨论】:

  • 很好,但仍不能解决问题:我想收到有关这些的通知。如果无法识别这些无意的guaranteed-invalid values,那就是语言设计错误;类似于try { /* ... things... */} catch { /* empty */ },会浪费数百万小时。
  • @atoth 这不是语言设计错误,而是 CSS。不要像 C++ 那样考虑它。 CSS 变量不像其他变量那样工作。当使用具有属性的变量时,您只能知道无效的计算(我只说)。使用您提供的代码,您无法知道它是否无效(除非您实现自己的算法)。识别这一点的唯一方法是使用属性内的变量,读取该属性的计算值,然后检查。另请注意,计算值时间在属性正在运行时触发,而不是在变量使用另一个属性时触发。
  • @TemaniAfif 通过读取计算属性是指在元素上使用它吗?说p { font-size: var(--invalid-var); }?因为在那种情况下我们会遇到空字符串问题,所以它将是p { font-size: ; }
  • @atoth 不,你不会有空字符串,但你会回退到另一个值。从规范:发生这种情况时,属性的计算值是属性的继承值或其初始值,具体取决于属性是否被继承 - 所以在你的例子中(p{font-size:var(--invalid-var):} ) 你不会有任何空字符串,但就像你什么都没做一样,默认的字体大小将应用于 p。
  • @atoth 检查一下:jsfiddle.net/ugvnewy0 ...您认为根目录中的变量无效,并且从逻辑上讲,使用它的 h1 将是错误的,但不是。我已经再次定义了相同的变量,并且对于一个 h1 应用了它,所以它很好,如果我删除第一个 h1:jsfiddle.net/ugvnewy0/1 那么没有任何问题,并且根内部的变量没有被使用,所以在这种情况下没有任何东西是无效的。您不应该在变量级别上思考,而应仅(且仅)在属性级别上思考,因为变量在使用之前没有意义。您对此有何看法:jsfiddle.net/ugvnewy0/2 无效?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-07
  • 1970-01-01
  • 2019-04-19
  • 2014-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多