-
Notifications
You must be signed in to change notification settings - Fork 693
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] Computed value of a negative calc unit that doesn't allow negative lengths. #434
Comments
cc @SimonSapin |
For the record, Firefox does follow the spec correctly, but clamps the value in |
For properties where the computed value is a length (i.e., calc()s are computed at computed value time) like I think the spec is still wrong for properties that accept calc() but where calc() is not part of the computed value space since it can be fully computed by computed value time (e.g., |
Yeah, and WebKit (and Blink) also clamp (edit: lengths, of course) at computed value time, see https://github.com/WebKit/webkit/blob/e999a05729f1c284fd6e734b88e81a2b078ed80f/Source/WebCore/css/CSSCalculationValue.cpp#L195 |
Note that getComputedStyle() returns the used value for a number of length-using properties, so that pollutes the data quite a bit here. WebKit/Blink doesn't actually have a separate notion of "computed value" in the engine. |
The CSS Working Group just discussed The full IRC log of that discussion<fantasai> Topic: CSS Values and Units: clamping calc()<fantasai> github topic: https://github.com//issues/434 <myles> fantasai: this question was about when things get clamped, if you have a property which doesn't accept negative lengths, for example, the spec says that the used value is clamped, but the computed value is not clamped, and there is some disagreement about whether that is waht is implemented <myles> fantasai: dbaron says that calc() is computed at computed value liek font size <fantasai> dbaron's comment: <fantasai> For properties where the computed value is a length (i.e., calc()s are computed at computed value time) like font-size, we clamp to nonnegative values at computed value time. For properties where the calc() expression is part of the computed value space (like padding-left) we have clamping at used value time (both in the GetComputedStyle code and in the code that actually uses the value). <fantasai> I think the spec is still wrong for properties that accept calc() but where calc() is not part of the computed value space since it can be fully computed by computed value time (e.g., font-size). <fantasai> https://github.com//issues/434#issuecomment-243933445 <myles> Rossen: to further TabAtkins's latest point, some or most of this is referring to getComputedStyle() which returns used values not computed values <myles> Rossen: it seems like WebKit and blink don't have a separate notion of computed values, and this is a transient value for them <myles> dbaron: there is some value which gets inherited. If you have "25% - 30px" and you say this is the computed value and it gets inherited to something which clamps differently, it should be clamped differently <myles> Rossen: but you don't know that 25% gets resolved to something > 25px <myles> fantasai: but you do know this for some properties <myles> fantasai: for padding-left you don't know this, but font-size, you do know this <myles> fantasai: you can resolve this at computed value time, and you need to because the value at font-size needs to be computed to a length in order to resolve em <myles> Rossen: font-size is the only property which resolves percentages outside of layout <myles> fantasai: dbaron: no <myles> Rossen: .... <myles> Rossen: ok. <myles> fantasai: dbaron, do you have a proposal? <myles> dbaron: not off the top of my head <myles> dbaron: i could write one <myles> fantasai: yes please <myles> dbaron: we need a distinction where calc() is resolved at computed value time and where calc() is part of a computed value. these needs separate rules <myles> fantasai: ok. <myles> fantasai: in the first case, we would do the clamping at computed value time, and the second case, it would be at used value time <myles> dbaron: yes <myles> Rossen: how is this observable? <myles> dbaron: the difference is observable through inheritance. but also, some fo the combinations of ways of specifying it, it doesn't make any sense <myles> fantasai: let's resolve <myles> Rossen: we need a proposal <myles> fantasai: i can write a proposal <myles> fantasai: w/ dbaron's review <myles> Rossen: let's see the prose before we resolve <myles> fantasai: sounds good |
Current text is:
I propose we change this to:
|
Okay, so there are two interpretations of what dbaron said:
For example,
The latter seems slightly simpler, but since it means that a property only clamps exactly one time, a property that currently only has computed-value units and then later adds used-value units would change behavior in an author-observable way. The wording for each of these options would be different, so we need the WG to resolve on which one. |
The CSS Working Group just discussed The full IRC log of that discussion<astearns> topic: [css-values] Computed value of a negative calc unit that doesn't allow negative lengths.<astearns> github topic: https://github.com//issues/434#issuecomment-310183908 <fantasai> TabAtkins: Spec text previously said that you can put negative numbers into calc(), it's fine, because we can't in general tell if it's negative or not <fantasai> TabAtkins: we do a clamping at some point if it needs to clamp to a particular range <fantasai> TabAtkins: Spec previously said that clamping happens at computed value time, but you can't always tell, e.g. width has to happen at used value time <fantasai> (and font-size has to happen at computed value time) <fantasai> TabAtkins: fantasai and I discussed and realized there are two possible interpretations of this conclusion <fantasai> TabAtkins: for properties that clamp at computed value time <fantasai> TabAtkins: can clamp through at computed value time <fantasai> TabAtkins: For properties that clamp at used value time, some things can clamp at computed value time <fantasai> TabAtkins: So do those properties clamp both at used and computed value time, or just at used value time? <fantasai> Florian: So for multi-stage examples if you can't clamp, you keep a calc() expression, right? <fantasai> TabAtkins: If you're width is calc(5px-5%) it'll stay as that at computed value, clamps at used value <birtles> I think we want to clamp as late as possible -- since animation operates on computed values (more or less) <fantasai> Florian: But if you clamp at calc(5px-5em) can clamp at computed value <fantasai> TabAtkins: If we clamp only at used value time, we need a definition of which property is which kind of computation <fantasai> TabAtkins: And then, if we ever add a unit that does used value time computation to a property that currently clamps at computed value time, it would change behavior <fantasai> TabAtkins: So I prefer clamp at all times behavior <fantasai> dbaron: I was going to say I prefer the other one <fantasai> dbaron: birtles said same thing on IRC, but was thinking about animations <fantasai> dbaron: I was thinking essentially of things like width: calc(-5px) vs width: (0%-5px) vs width: (0-5px) vs width: (10%-5px) <fantasai> TabAtkins: You can't add 0% to 1s, so while we technically can resolve zero immediately, we would treat it like any other percentage <fantasai> dbaron: Still worth thinking about animations <dbaron> s/vs width: (0-5px) // <fantasai> Florian: If we go that way, pretty important to go the way Tab says for 0%, otherwise discontinuity between 0% and 0.00001% <birtles> specifically my concern is you want to interpolate using the unclamped values and then clamp <fantasai> TabAtkins: Don't understand animations issue <fantasai> TabAtkins: font-size resolves everything at computed time already <fantasai> TabAtkins: So animations should see value of 0 for 0px, don't see why width should be different <fantasai> dbaron: You can have a calc() that's a result of interpolation <fantasai> dbaron: If one of the end points does different things than the intervening value.. <fantasai> TabAtkins: If the values are different, then the middle value will always be a valid value anyway <fantasai> ... bouncing ... <fantasai> TabAtkins: If it's a used value time unit involved, then it'll always stay as a calc() <dbaron> (bouncing meaning timing functions that go outside 0-1) <fantasai> Florian: None of these allow us to have results earlier, to get fully resolved value at computed value time ..? <birtles> e.g. if you support calc() for opacity and interpolate between calc(-1) to calc(3) you'll get different results if you clamp the endpoints before interpolating <fantasai> TabAtkins: Just feels nasty and weird if font-size can clamp its values at computed value time, but width can't even if it uses the exact same value <fantasai> TabAtkins: And also, as I said before, if we add a used-value time unit to a computed-value-time-only property, it would change behavior <fantasai> TabAtkins: observable in animations as well as OM <fantasai> TabAtkins: If we say that a property only has computed value time units, then it can never gain a used-value time unit <fantasai> Florian: Why? <fantasai> TabAtkins: Because it will change from clamping at computed value time to clamping at used value time, seeing raw calc() value in the animation <fantasai> TabAtkins: Difference is e.g. animated from -1000px to 1000px, would stay at 0 for first half if doing used value time, and would animate from 0 to 1000px over full range if doing computed value clamping <fantasai> dbaron: What do implementations currently do? <fantasai> TabAtkins writes some tests <fantasai> TabAtkins: Looks like in Chrome at least, appears to delay width clamping to used value time right now <TabAtkins> http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5256 <fantasai> TabAtkins: Spends half of the animation sitting at zero <fantasai> TabAtkins: wait, this is inconsistent <TabAtkins> http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5257 <fantasai> ?: Does the other behavior. never sticks at zero. <fantasai> TabAtkins: Sounds like no interop <gsnedders> s/?/Myles:/ <RachelNabors> BAHAHAHAHA... Tab. <myles> s/?: Does/Myles: Safari does/ <fantasai> astearns: Think we should kick this back to github for testing, come back with animation data <fantasai> astearns: Anything else to bring up on this topic? |
Need to see more testing results before this goes on the agenda again. |
I've written these tests that check whether an animated negative calc value is clamped at computed value time (and thus a range of negative values aren't present in the animation) or used value time (where a range of negative values will be present in clamped form for a duration in the animation) astearns/web-platform-tests@da5892f The results I'm seeing are all over the place. Pass means clamping is happening at used value time (mostly). Fail means it's clamping at computed value time. width and padding-left have the same results width-up width-down opacity-up opacity-down font-size up font-size down |
Alan, which version of FF did you test? The results may not differ but our animation code has changed significantly from version 57 onwards. |
I'm on Mac nightly, so 58-ish? - I'll edit in the exact version number when I get back to the office tomorrow |
That's recent enough--thank you! |
It may also be worth testing Firefox 56, though, since that's the code currently shipping. |
FWIW, I'd note that the Firefox results make sense to me: the properties where calc() can be handled at computed value time "fail", and the properties where it needs to be deferred to used value time "pass". |
Agenda+ because we have test results (above) and a proposal (#434 (comment)) and this is blocking CR update of Values and Units for months now so it would be really nice to resolve and republish. |
@dbaron That has the forward-compatibility problems noted by @fantasai in #434 (comment) - if a property initially accepts only computed-value-time units, it would be clamped at computed-value time, but if it later starts accepting used-value-time units, we'd have to move it to clamping at used-value time, which is observably different. Thus the proposal to clamp at both spots - computed value clamping if possible, used-value clamping otherwise. That way a |
The Working Group just discussed The full IRC log of that discussion<dael> Topic: [css-values] Computed value of a negative calc unit that doesn't allow negative lengths<dael> github: https://github.com//issues/434 <dael> astearns: I added some tests with idea we would want to be picking either use or computed time. Sound proposal is to clamp as soon as possible. Correct? <bkardell_> present + <dael> fantasai: Not quite. To clamp them both...twice effectively. <dael> fantasai: Some values you can calc through at the beginning and others you can't. <fantasai> Summary of the issue / proposal : https://github.com//issues/434#issuecomment-310183908 <dael> dbaron: I think what I suggested is that when the value...when all values of prop can be computed through at computed value you clamp t computed value time. If not you clamp at used value time <dael> TabAtkins: That is what we're saying <dael> fantasai: No it's not. <dael> fantasai: There's two proposals. One is you clamp at each stage if it's possible at thtat stage for values under consideration at that moment. <dael> TabAtkins: The answer is the forward compat one. A prop is used value clamping if any property needs used value time to tell. It will have an observable effect if we later add an item that is used to a clamp. The clamp as early as you can has no observable effect when we add new things to value space. <dael> florian: So is there an argument against that? <fantasai> s/at that moment/; other is you clamp when it's guaranteed to be possible for that property in general./ <dael> astearns: My question is since clamping at used value appears to be slightly useful for animmations could we only clamp at used value time? <dael> TabAtkins: That might be possible <dael> fantasai: I'ts not because font size prop needs to compute through to ems can be computed. <dael> TabAtkins: Is that true though... <dael> ??: I think so <dael> TabAtkins: What's wrong with ems computing to a calc. <dael> fantasai: ems are a length, they resolve to px <dael> TabAtkins: THat's current. What's wrong with the other way around. <dael> TabAtkins: It eentually falls through to layout. Only differencec is what things you can observe at computed value time. <dael> fantasai: It means you'll carry a calc around that's 50px+100%+2em you have to carry that and insert it into a margin that's a descendant of a descenent .... are you crazy? <dael> TabAtkins: Yeah, that would be the technical consiquencce. Every situation here is bad. <dael> dbaron: That's bad for impl complexity and performance if you say you can never simplify. <fantasai> s/..../but still have it resolve on the parent on the original element on which it was declared/ <dael> TabAtkins: Sure. <dael> florian: What's wrong with clamp as soon as you can. It sounded good to me. It's fine with animations. <dael> TabAtkins: Someone advocating for that would have to argue for it because I don't know. <gregwhitworth> "as soon as you can..." <dael> astearns: I'm still unclear. <dael> TabAtkins: florian means what we're suggesting. <dael> florian: As soon as you can based on alues, not based on which property it's in <fantasai> A) Clamp as early as possible based on values. <dael> dbaron: % will behave differently depending on how they behave for prop <fantasai> B) Clamps as early as possible based on the property. <dael> TabAtkins: We're saying as early in the context of a property. Since in the property you can tell if you can know at computed and clamp them or you wait until used. <dael> dbaron: Are there cases...where we distinguish between calc 10% and 10% doing something different. <dael> TabAtkins: I don't think so. In position % don't resolve to a simple pixel value, but still a bare % goes to same in or out of call <dael> fantasai: If it's negative. We throw those out at parse time <dael> dbaron: If we want to throw out neg it also makes sense to simplify away the calc. <dael> dbaron: If you're at a point where you can fix the negative you should comput calc to a single value <dael> TabAtkins: That's against our general consesus to maintain calc structures somewhat so that authors get to look at a regular thing. I've argued against that, but that was what the group wanted. <dael> florian: [missed] <astearns> s/[missed]/editor concerns/ <dael> dbaron: I don'ts ee how you maintain a calc structure while clamping. If you have 50px+2em and you know an em is large, do you change the em or do you turn it into 0px? <florian> a/[missed]/channelling glazou: when possible, keeping what the author wrote helps with authoring tools/ <dael> TabAtkins: For animation it's 0px <dael> dbaron: But we're talking what the computed value is <dael> TabAtkins: Well, what the animated value is. It's mostly the cocmputed, but sometimes diverges. <dael> TabAtkins: Big obserable thing is in your animated behavior <dael> dbaron: I guess...you could compute it to calc 0px rather then 0px. But it seems weird to deal with clamping but not simply expressions. <dael> astearns: Seemes weird to me to have a clamp happen but then give the non-clamped expression and the person using it doens't know if it's eval as expression or clamped value. <dael> TabAtkins: I don't have a strong opition but people have obj to removing calc before. <dael> fantasai: Removing calc should be a sep/ issue <dael> dbaron: It would also be useful to have links to the other decisions. <dael> TabAtkins: I recall glazou being a proponent of maintaining calc <dael> astearns: fantasai in IRC had 2 comments [reads] <dael> astearns: My understanding is we're going with option A <dael> astearns: Is that correct? <dael> florian: Yes, I think so <dael> astearns: What if we resolve on option A: Clamp as early as possible based on values. and I'll open a new issue as to what to do with calc when they're clamped <dael> dbaron: I'm uncomfortable agreeing to clampa t a time when we're not agreeing to simplify calc at the same time <dael> florian: Would you obj to not simplifying or is there another option <dael> TabAtkins: I'm fine with simplifying. There were arguements against it before. <dael> dbaron: I think we should table and go back to look at those arguments. <dael> astearns: I'll add a comment that we need to look at why we had been decising to preserve calcs. This being a new situation where we're clamping the value I suspect the previous arguments about preserving calc-ness will go out the window. <dael> florian: astearns when you make that it's good to mention glazou. <dael> astearns: I will tag him on it. <dael> TabAtkins: This is the only thing blocking CR and V&U is quite out of date. Can we do a new CR with this unfinished and get it up to date? <dael> astearns: How many other changes are in the changes section? <fantasai> https://drafts.csswg.org/css-values-3/issues-cr-2016 <dael> TabAtkins: I'll look. A decent amount. A number of new units <dael> astearns: And we're in CR? <dael> fantasai: The new units are in 4. <dael> TabAtkins: Let me linkt he changes. <dael> astearns: Given we're in CR I don't htink we can ask for updated before we republish. <dael> TabAtkins: Then let's close it no change and re-open it because this is preventing us from publishing. <dael> fantasai: I think we can ask for republish and explain this is a minor issue and still open and we'll deal with it. <dael> astearns: Republishing and knowing we have to do it again is also dumb. I'd rahter wait. <dael> florian: Does spec have the thing we're likely to resolve to? <dael> TabAtkins: let me look <dael> TabAtkins: Current spec says always clamped at used value which is the thing we agreed to not do <dael> [laughs] <dael> florian: So resolve unless glazou objects? <fantasai> s/the thing/the one thing/ <dael> astearns: I don't want to rush this through. <dael> astearns: I'm sorry. <dael> TabAtkins: I'm jsut frustrated that we cna't publish because proccess. I'd rather publish and publish again in a montht hen have a month of buggy TR draft. <dael> astearns: I agree on regular WD but CRs are extra work. |
In the discussion above we talked about (but did not resolve) on what happens to calc() expressions when the value is clamped. I believe there was consensus on the call to simplify the calc() expression in that case, as the clamping changes the value significantly from what the expression might appear to be. We've had discussions in the past about preserving calc() expressions for tooling. It might be weird to have a "calc(50px)" value maintain the expression for a computed value, but a "calc(-50px)" value get simplified to "0px" upon clamping at computed value time. But it might be useful to represent the clamping in this edge case. Do you have an opinion, @therealglazou? |
I am fine with the resolution from confcall 20171213. |
The Working Group just discussed
The full IRC log of that discussion<dael> Topic: [css-values] Computed value of a negative calc unit that doesn't allow negative lengths.<dael> github: https://github.com//issues/434 <dael> Rossen_: This was intro last week. We resolved to clamp as early as possible, but not how to return computed values based on thsi clamping. We wanted to hear about it from a few people, one of them was glazou. <dael> Rossen_: That's the first topic. <dael> Rossen_: Is TabAtkins or fantasai on> <dael> fantasai: I'm on, but no computer. <dael> TabAtkins: glazou didn't respond and I haven't had time to go through and dig up previous issues. I'm fine resolving now and waiting for compalints later if there are any. <dael> Rossen_: Let me get us on the resolve. Previously we said clamp negative clamp as soon as possible. <dael> plinss: We didn't actually resolve. <astearns> s/plinss/astearns/ <dael> Rossen_: Ah, thank you. So we didn't resolve. But there was consensus on clamping as early as possible, right? <dael> TabAtkins: I believe so. <dael> Rossen_: Proposal is negative calc units are clampped as early as possible <dael> ??: per value or per prop? <dael> Rossen_: I believe per value <astearns> s/??/fantasai/ <dael> fantasai: That was key question, per property or per value <dael> Rossen_: I assumed it was per value and if it was given to the property it inherits <dael> astearns: Yes, it was def. per value. <dael> TabAtkins: mmhmm <dael> Rossen_: right <dael> Rossen_: So the consensus was to try and clamp those as early as possible. There was not consensus on how to return computed values. As calc with negative value inside or return the clampped value. <dael> Rossen_: So we could resolve on clamping and leave serialization out. TabAtkins or fantasai preference? <dael> TabAtkins: Tha'ts fine with me. The q was if you have a calc that's 50px-2em and that's negative at calc time do we simplify to calc0px rather then keepign the original. I'm fine simplifying the internal of the calc to the clampped value. I think that's what dbaron wanted. <dael> dbaron: I think clamping and simplificiation should go together. If we're clamp we should also simplify. <dael> TabAtkins: That happens already, we collapse units together. But if we have units that we know will be clampped is the topic. <dael> dbaron: When you can resolve between px and em and know it's negative I think you also simplify to px. <dael> TabAtkins: I'm fine with that. <dael> Rossen_: And the serialized value is whatever the clampped value? <dael> TabAtkins: With a calc around it. <dael> Rossen_: Other opinions? <dael> Rossen_: Objections on resolving to clamp negative calc unit values in context as early as possible and then return the clampped calc as a resolut of the computed style. <dael> RESOLVED: resolve to clamp negative calc unit values in context as early as possible and then return the clamped calc as a result of the computed style. <dael> dbaron: We're saying clamp and simplify. <dael> TabAtkins: Some simplification is specced. This is collapse all units together that can be figured out. So we'd collapse em with px etc. <dael> fantasai: You have to do that for inheritence to work. <dael> TabAtkins: Yeah. <TabAtkins> Right now we already simplify calc(1px + 2px). Reoslution is to also simplify calc(1px + 1in) at computed/used value, and things like calc(1px + 1em) at the point where that's possible. <dael> RESOLVED: resolve to clamp negative calc unit values in context and simplify as early as possible and then return the clamped calc as a result of the computed style. |
Ok, I've checked in the following changes:
@emilio @tabatkins Can you let me know if that seems adequate? |
👍 |
Looks good to me, thanks! Maybe noting explicitly that clamping should not be done at specified value time is worth it? WebKit / Blink are buggy here wrt numbers / integers IIRC. Haven't checked if it's something mentioned in other places of the spec. |
@emilio OK, added parenthetical about specified values.
|
Closing out per @emilio’s verification over IRC. |
…lues. Linkify different types of values. #434
In the CSS values spec, section 8.1.4. Range Checking:
Note that the used value is expected to be clamped, but not the computed value. Both Blink and Firefox (at least, probably other engines too) clamp the value at computed value time, as can be seen running the following test, where all the properties that don't accept negative lengths (like
font-size
,padding-xxx
, etc.) report a computed value of0px
instead of the expected-1px
.The text was updated successfully, but these errors were encountered: