为什么 calc(50% + 0) 是错误的?

Why is calc(50% + 0) an error?

在测试一些新布局时,我发现自己在一处写字

.test1 {width: calc(50% + 0);}

令我惊讶的是,它没有用。
在确认我在任何地方都没有打字错误后,我不得不得出结论,浏览器拒绝了这个错误。然后我想这可能是我正在测试的浏览器中的一个缺陷,但另一个浏览器的行为是一样的!

那么这个表达式有什么错误呢?哪里出错了?

p {border:2px solid green}
.test1 {width:calc(50% + 0);}   /* wrong! */
.test2 {width:calc(50%);}       /* OK */
.test3 {width:calc(50% + 0px);} /* also OK */
<p class="test1">test 1</p>
<p class="test2">test 2</p>
<p class="test3">test 3</p>

(顺便说一下,我向你保证我无意在生产代码中使用它;这只是在测试中出现的东西。)

这是由于Type Checking

At + or -, check that both sides have the same type, or that one side is a <number> and the other is an <integer>. If both sides are the same type, resolve to that type. If one side is a <number> and the other is an <integer>, resolve to <number>.

If an operator does not pass the above checks, the expression is invalid.

您当前的代码有两个值,50% 是 percentage,0 是 integer/number。它不符合 类型检查.

的规则

对于Poke的评论:

引用自Computed Value

Where percentages are not resolved at computed-value time, they are not resolved in calc() expressions, e.g. calc(100% - 100% + 1em) resolves to calc(0% + 1em), not to calc(1em). If there are special rules for computing percentages in a value (e.g. the height property), they apply whenever a calc() expression contains percentages.

Note: Thus, the computed value of a calc() expression can be represented as either a number or a tuple of a dimension and a percentage.

所以可以说50% + 10px是类型检查的一个例外,在文章的计算值部分有介绍。

这是因为,表达式 (50% + 0) 由两种不同的类型组成。

您可能会认为 50% 是一个百分比,而 0 是一个 integer/number,并且不符合类型检查规则。但那是不正确的。不要将它与 units 混淆。 px, em, %都是dimension-tokenlength类型的units。允许两个不同的units,但必须是相同的type。不允许两个不同的types

W3C says this about types:

A math expression has a resolved type, which is one of <length>, <frequency>, <angle>, <time>, <number>, or <integer>. The resolved type must be valid for where the expression is placed; otherwise, the expression is invalid. The resolved type of the expression is determined by the types of the values it contains. <number-token>s are of type <number> or <integer>. A <dimension-token>’s type is given by its unit (cm is <length>, deg is <angle>, etc.).

您的表达式的左侧:50%, 50px, or 50emall unitslength 类型,它们是 <dimension-token>s, and the right-side of your expression: 0 is an integer type which is a <number-token>

与@Manoj 一样,+- 运算符明确限制操作数具有相同的 类型 lengthtimenumber-tokens.

在上面的后面参考:

At + or -, check that both sides have the same type, or that one side is a <number> and the other is an <integer>. If both sides are the same type, resolve to that type....

总结:

50% + 0px → Both are of the same type i.e. 'length
50% + 0   → Left is 'length' type and the right is 'integer' type.

50%(百分比)和 0(Int)是 2 种不同的数据类型,就像整数 (Int) 和字符串的不同一样,两者都需要属于同一类型才能执行计算。