为什么具有非法值的 `calc()` 宽度不会被忽略?

7

这个问题的启发,我发现了这个有趣的现象。

由于负宽度是非法的,因此应该被忽略,我期望像width:-200px;width:calc(0% - 200px);这样的样式属性不会产生任何效果。对于第一个样式属性确实如此,但是对于第二个样式属性,它并没有被忽略:而是使用了0的宽度。

请看下面的例子:

div {border:1px solid; background:lime;}

#badwidth {width:-200px;}

#badcalc {width:calc(0% - 200px);}
Div with bad width:
<div id="badwidth"> </div>

Div with bad calc:
<div id="badcalc"> </div>

如果忽略宽度属性,div 将会是其全宽(与顶部的那个相同)。然而,它被折叠为 0(看到左边的黑线;那就是边框)。
为了参考,这里有一些其他的 div,以演示 1) calc(0% - 200px) 本身并不是错误,2) 它们可以正常工作,第一个代码片段是异常情况。

div {border:1px solid; background:lime;}

#calc {margin-right:calc(0% - 200px);}
Plain div:
<div> </div>

With calc(0% - 200px) in a place where it's OK:
<div id="calc"> </div>

那么,为什么普通宽度和计算宽度的行为不同呢?
如果只是一个浏览器,我会称其为错误。但他们都以相同的方式处理这个问题!所以一定有些东西我忽略了。是什么呢?


我几乎不认为这种行为是一个错误或异常:我期望 width: calc(100% - 500px) 在 500px 及以下的宽度结果为0;如果在0到499px之间宽度回到默认的 auto,我会感到恼火!:-) 对于你提到的 0% 的例子,我们人类知道它永远不会产生正值,所以它看起来是一种奇怪的行为,但在其他例子中并非如此。CSS WG 和浏览器供应商必须考虑许多情况。 - FelipeAls
1个回答

8
您所遇到的问题是 calc 表达式的计算结果和规则中允许的值不同。根据规范CSS Values and Units
引用如下:

虽然某些属性允许使用负长度值,但这可能会使格式化变得复杂,并且可能存在实现特定的限制。如果允许使用负长度值但无法支持,则必须将其转换为最接近可支持的值。

在此情况下,-200 会被四舍五入为 0,因为它是 width 可支持的最接近的值。 编辑 前面的部分还说明了以下内容:
引用如下:

属性可能会限制长度值的范围。如果该值超出了允许的范围,则声明无效并且必须被忽略。

当声明 width: -200px 时,该值超出了允许的范围,因此被忽略。但是,似乎 calc 在检查之前计算 -200,将其四舍五入以使其在可接受的范围内,因此它不会被忽略。 更新

感谢 @CBroe 提供的calc规范的参考链接

在calc()内部不执行值的解析时间范围检查,因此超出范围的值不会导致声明无效。但是,表达式产生的使用值必须被夹紧到目标上下文允许的范围内。

由于不允许小于0px的宽度,因此这三个声明是等价的:

width: calc(5px - 10px);
width: calc(-5px);
width: 0px;

请注意,width: -5px并不等同于width: calc(-5px)! 在calc()之外的超出范围的值是语法无效的,并会导致整个声明被删除。

如果适用的话,width:-200px 的值也会被四舍五入为0。但是,正如您在第一个示例中所看到的那样,它并不适用。 - Mr Lister
请看我的编辑 - 在将最终值与属性规则进行检查之前,必须先评估calc - chazsolo
2
然而,对于calc,这里明确指定了它如何处理超出范围的值:https://drafts.csswg.org/css-values-3/#calc-range:“在calc()内不执行值的解析时范围检查,因此超出范围的值不会导致声明无效。但是,表达式产生的使用值必须被夹紧到目标上下文允许的范围内”,这就是这里发生的情况。calc给出了一个负结果,但对于宽度来说是不允许的,因此结果值被“夹紧”为0。 - CBroe
@CBroe 哇,你能把那个发表为答案吗? - Mr Lister
@MrLister:随着chazsolo对答案的编辑,我认为我们已经解决了这个问题。只需给他点赞;) - CBroe
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接