Repository navigation
[css-values] Differences between calc() handling for <length-percentage> values. #3482
Description
I was doing some work in Gecko and realized various inconsistencies with how we treat calc(). I saw that other browsers have other (different) inconsistencies. I'm fixing some of those where it seems reasonable and we all agree. But I'm having trouble to find what the model is supposed to be.
I'll try to break this down to simpler questions...
Should calc(%) always be treated the same as %
It looks to me like it should, but in Gecko right now this is not always the case. For example, in the containing-block-size quirk, Gecko will only apply it to non-calc percentages, intentionally:
<style>
body { margin: 0 }
div {
height: 100%;
float: left;
width: 50%;
background: green;
}
div + div {
height: calc(100%);
background: orange;
}
</style>
<div></div>
<div></div>Should calc(% + 0px) be equivalent to calc(%)?
I intuitively thought it should, but browsers differ here. For example, these two tables look different in blink / webkit:
<!doctype html>
<table border>
<tr>
<td style="width: calc(50%)">x</td>
<td style="width: 100px">y</td>
</table>
<table border>
<tr>
<td style="width: calc(50% + 0px)">x</td>
<td style="width: 100px">y</td>
</table>I think they should render the same though (though I could be convinced otherwise).
Should calc(<length> + 0%) be the same as calc(<length>)?
I tend to think it should not, since we special-case percentages in quite a few places, and 0% is not the same as 0px everywhere (I'm pretty sure it's not the same in grid track sizing for example). Also intrinsic sizing, and this is a test passing in all browsers:
I think the simplest model to get something consistent and simple implementation-wise is to keep track only whether percentages were specified, and make % + 0px always the same as %, or alternatively track both whether lengths and percentages were specified (though that's a bit more complex).
Activity
Loirooriol commentedon Jan 4, 2019
Should
calc(%)always be treated the same as%https://drafts.csswg.org/css-values-4/#calc-serialize says
I think it would be bad if the serialization is the same but the behavior can be different.
Should
calc(<length> + 0%)be the same ascalc(0%)?In general they seem clearly different, I think you meant
calc(<length>)instead ofcalc(0%).And I agree the
0%should not disappear, this seems already specified in https://drafts.csswg.org/css-values-4/#calc-computed-valueShould
calc(% + 0px)be equivalent tocalc(%)?Not that sure about this one. Theoretically I think they may be considered to be different, but in practice I would probably expect e.g. CSS Tables to say they should be equivalent in your example.
Ernedar commentedon Jan 4, 2019
It depends how the
calc()is threated. In my mind thecalc()is threated like mathematical operation similar to (A + B) so for example ifcalc(A + B)is same as (A + B) so thecalc(%)will be same as (%) and therefore is no matter if it is with out without those brackets. The different case is when you are using it to calculate something in real time in depency on some attribute likevworvh. If it is the real time case,calc(%)will never be same as % because browsers are limited in rounding numbers.emilio commentedon Jan 4, 2019
Note that browsers do simplify away 0% and 0px in a bunch of cases, though I'd consider the 0% disappearing a bug.
emilio commentedon Jan 4, 2019
Also:
Yes, I edited the original post :)
tabatkins commentedon Jan 4, 2019
calc(%) vs %
Yeah, should be the same as much as possible, because
calc(%)will serialize to%, as @Loirooriol says.calc(% + 0px) vs calc(%)
Sure. There's no case in which these two should be different. Lengths never have magical behavior, so adding it to a % shouldn't add any complications, and in the rare cases where length+% is different than just resolving the % and adding the two together (bg-position), a 0px length is still a no-op.
More specifically, the average of
calc(% + 1px)andcalc(% - 1px)will, in every case I can see, be the same as ascalc(%).calc(length + 0%) vs calc(length)
No, these are different. %s can bring magic, as they sometimes resolve to intrinsic values or behave as auto. Same argument as above, but with opposite result: the average of
calc(length + 1%)andcalc(length - 1%)is not, in some cases, the same ascalc(length).emilio commentedon Jan 5, 2019
Alright, so you're in agreement with my intuition, that's great :)
Now we just need to fix implementations then, and maybe add a note to the spec?
Simplify computed::LengthOrPercentage and friends.
Bug 1517511 - Simplify computed::LengthOrPercentage and friends. r=he…
style: Simplify computed::LengthOrPercentage and friends.
Bug 1517511 - Simplify computed::LengthOrPercentage and friends. r=he…
Bug 1517511 - Simplify computed::LengthOrPercentage and friends. r=he…
Simplify computed::LengthOrPercentage and friends.
fantasai commentedon Jan 10, 2019
The percentages of bg-position aren't special, they're relative to the size of the bg positioning area - size of the image. Which maybe looks magic, but it isn't.
fantasai commentedon Jan 10, 2019
@emilio Wrt tables, see last paragraph of https://www.w3.org/TR/css-values-3/#calc-computed-value Your expectation is correct, we just let UAs do weird things in tables because tables are weird.
68 remaining items
style: Remove LengthPercentage::was_calc.
[css-values-4] Ignore non-zero lengths when falling back to auto on t…
Fix translate-interpolation.html.
Bug 1737211 - Fix translate-interpolation.html. r=layout-reviewers,boris
Fix translate-interpolation.html.
Bug 1737211 - Fix translate-interpolation.html. r=layout-reviewers,boris
Fix translate-interpolation.html.
Bug 1517511 - Simplify computed::LengthOrPercentage and friends. r=he…
Bug 1577139 - Remove LengthPercentage::was_calc. r=heycam
Bug 1559231 - Make offset-anchor animatable. r=birtles
Bug 1737211 - Fix translate-interpolation.html. r=layout-reviewers,boris
Auto table layout should treat calc(% + 0px) as percentage
Bug 957915 - Handle calc(%) on tables. r=mats
Bug 1541477 [wpt PR 15950] - In table layout, treat calc(% + 0px) as …
Auto and Fixed table layout should treat calc(% + 0px) as percentage