Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-values] <percentage> shouldn't be able to resolve to <number> in calc() #1463

tabatkins opened this issue May 25, 2017 · 4 comments


Copy link

tabatkins commented May 25, 2017

In #1462, I talk about the problems inherent in letting "number"-typed expressions in calc() ever resolve as equivalent to "length"/"angle"/etc expressions. This was already disallowed in Level 3 calc(), so it was okay.

However, I just realized that Level 3 calc() does allow <number> and <percentage> to be equivalent, which brings up the exact same issues.

Now, in plain CSS, the difference doesn't really matter - because <number>s can multiply with each other endlessly, it's okay to have an expression like calc(1% * 1%) for 'opacity' (as it resolves to "number"), but the exact same calc() would fail immediately in 'width' (as its type would be length²). Similarly, it would mean that calc(1 + 1%) is valid in 'opacity' but invalid in 'line-height'. This all complicates the rules quite a bit in Level 4 calc(), or Typed OM.

I propose that we amend calc() to prevent <percentage> from resolving against <number>. This has no practical effect on devs - since <number> and <percentage> are just rescaled "units" in 'opacity', there's never a need to add them together in calc, or multiply two or more percentages (you can just convert them to numbers by shifting the decimal point, then add/multiply them). However, it drastically simplifies the necessary type-tracking spec text I'm writing for Typed OM (which Level 4 calc() will reuse).

Copy link

Crissov commented May 25, 2017

Aside: We should never have had unitless <number> where real scalars are allowed.

Copy link
Member Author

Correct, but that's not relevant here - <number-token> is always a "number" type in calc(); width: calc(0); is invalid, because 'width' doesn't accept <number> in its grammar.

Copy link
Member Author

Agenda+ for resolution. Also, some trivial testing (seeing if opacity: calc(.25 + 25%) is supported) in Chrome and Firefox shows that they won't be affected by this change, as they currently treat it as invalid anyway.

Copy link

The CSS Working Group just discussed <percentage> shouldn't be able to resolve to <number> in calc(), and agreed to the following resolutions:

  • RESOLVED: Accept proposal
The full IRC log of that discussion <astearns> topic: <percentage> shouldn't be able to resolve to <number> in calc()
<astearns> github topic:
<dael> TabAtkins: When you use % in calc it's can use it anywhere the usage would resolve a % against another type.
<dael> TabAtkins: Applies equally, but per spec it applies to numbers. THis would apply in opacity, for example. Problem is in typed OM when I'm trying to deal with types of expression how we desc in last F2F numbers have an empty type map.
<dael> TabAtkins: If we don't allow % against numbers they're easy to handle. It's always somet ype and I can later fill in the type.
<dael> TabAtkins: If it could resolve against a number I lose that ability. A % could be a type or none at all and that makes the algo harder to desc.
<dael> Florian: Clarification: opacity you have % or umber and it's the same or you have line height where % and number aren't combinable. Are there cases where you have % and number where they're combinable but not same.
<dael> fantasai: They're combinable in the sense where # and % in line height ultimately resolve to length.
<dael> fantasai: We could, in thoery, allow that.
<dael> TabAtkins: There's a reason not to. I'd like to never allow that. There's a reason to disallow that.
<dael> TabAtkins: It makes the type of numebr incoherent. It's typeless or has a type. It makes the algo to type check math extreemly more complicated.
<AmeliaBR> For line-height, % and number don't inherit the same: % gets converted to length before inheritance, number is converted at used-value time.
<dael> TabAtkins: Big problem in when you multiple unitless. If a number can represent a lneght if you multiple 1 x 2px is it a length or a length suqared?
<fantasai> AmeliaBR: Yeah, and in width, <length> and <percentage> have that same difference
<dael> TabAtkins: There's only two cases wehre this matters, line height and tab size. We could just add a unit. For now we're okay. Calc doesn't allow you to treat a number as a length.
<dael> dbaron: I'm not happy about treating # and % the same. # on line-height needs to be distrinct from %
<AmeliaBR> PS, for length + number, there are all the SVG properties to deal with, that treat number as equivalent to px
<AmeliaBR> (e.g., stroke-width, stroke-dasharray)
<dael> TabAtkins: They are. This is where % resolves to a number. Opacity is the obvious example. I propose we say a % never resolves to a number type.
<dael> fantasai: Does the % value of opacity compute to a number?
<dael> TabAtkins: I believe it computes to a number. That's what it has to do. Opacity uses 0 to 1 as a %. The two are eq.
<Florian> I'm with Tab here. The alternative seems to mean a lot of complexity for no good reason.
<dael> fantasai: I think it would be surprising if someone tried to to combine and it didn't work. If you're adding a variable to an inlined you'd have to be very careful.
<fremy> q+
<dael> TabAtkins: I agree. That's why we originally wrote % can resolve against #. But from a pratical standpoint dealing with types it doesn't work. You get an incoherent thing where numbers can sometimes be used as extra values. In the worst case you can never tell what type an expression is if a # shows up.
<dael> TabAtkins: If I wasn't writing spec text I wouldn't have suggested this.
<astearns> ack fremy
<dael> fremy: Edge does not support % in opacity. THis is the first time I heard you can. I would be fine saying % doesn't mix with numbers,
<dael> TabAtkins: No one, even browsers that allow %, don't allow them to mix in calc. Everyone is consistant in not allowing this, I want to fixt he spec.
<dael> astearns: By not allowing we're matching impl.
<dael> TabAtkins: Yeah.
<dael> dbaron: Some of that is because we don't have a spec ofr calc unit.
<dael> TabAtkins: It's a lack of support not a positive we're doing this on purpose thing. But removing it won't cause problems.
<dbaron> s/ofr calc unit/for calc() unit algebra/
<AmeliaBR> % for opacity was a relatively recent addition to the spec
<dael> astearns: Objections to codifying this limitation?
<dael> RESOLVED: Accept proposal

triple-underscore added a commit to triple-underscore/ that referenced this issue Jun 10, 2017
Specify that 0 parses as a <number> if it's ambiguous whether it's a
<number> or <length>.
Fixes w3c/csswg-drafts#489 .

Remove ability for percentages to resolve against numbers. Fixes
w3c/csswg-drafts#1463 .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet

No branches or pull requests

3 participants