#624: CSS: contain-intrinsic-size: auto, and converting to a shorthand property
Discussions
Comment by @LeaVerou Apr 28, 2021 (See Github)
My thoughts while looking at this:
First, this definitely solves a real problem. Indeed, it's quite a hassle if authors need to guess the correct intrinsic size for this property, and it creates a maintenance nightmare when there are a lot of elements whose intrinsic sizes need to be contained.
On the other hand, CSS has always been this nice reactive language in which things apply and then they stop applying without leaving any side effects behind. Unlike (common) programming languages, there are no ordered steps, the current state is always a function of what currently applies, and there is value in that simplicity. The concept of last remembered size that is introduced here breaks this fundamental assumption, introducing side effects that persist after properties have stopped applying. It introduces state that is not inspectable and has no obvious cause. Is there any other existing CSS feature that produces lasting side effects in that way? Have other ways to solve this problem been sufficiently explored that do not change the way CSS works so dramatically?
Comment by @vmpstr Apr 28, 2021 (See Github)
Thank you for your feedback!
The concept of last remembered size that is introduced here breaks this fundamental assumption, introducing side effects that persist after properties have stopped applying.
contain-intrinsic-size
only has an effect if we have size containment, so the side effect here is tied to the presence of size containment (whether introduced by contain
property directly or via something like content-visibility
). In other words, I claim that the side effect introduced here does not persist after the property has stopped applying -- it's just not the same property, if that makes sense. But that's a bit of a pedantic point. Other than that, you're right that this introduces a state that is captured at a time different from when the property begin applying.
Is there any other existing CSS feature that produces lasting side effects in that way?
I'm not aware of anything in CSS that relies on previous sizing like this. However, we do have things like content-visibility: auto
which depend on element visibility, relying essentially on IntersectionObserver
timing. There are also things like container queries, which selectively apply different styles depending on the current state / size of elements. It's not the same as contain-intrincis-size auto
, for sure, but I feel like it falls in a similar bucket of things that aren't exactly side-effect free.
Have other ways to solve this problem been sufficiently explored that do not change the way CSS works so dramatically?
The piece of data that we want to capture here is the size that really only the UA knows for sure. Script, for example, can get at this size and the advice that we've been giving developers is to use a polyfill of this feature, directly using ResizeObserver
or getBoundingClientRect
to set appropriate values of contain-intrinsic-size
at appropriate times. But in order for us to do this "automatically" in CSS we would need to snapshot this size before we apply size containment and use it at the time that size containment applies. So fundamentally, there is a timing dependency here that I believe is unavoidable.
Discussed
May 1, 2021 (See Github)
TODO: Lea leaves comment after breakout (Done)
@hober and I discussed this in a breakout today during our VF2F. We think that the improvement this feature offers over the existing JS library appears to be very incremental, so it appears that the benefit of adding this feature to the Web Platform does not outweigh the additional complexity, and the cost of breaking one of the fundamental assumptions of CSS.
Comment by @LeaVerou May 11, 2021 (See Github)
@hober and I discussed this in a breakout today during our VF2F. We think that the improvement this feature offers over the existing JS library appears to be very incremental, so it appears that the benefit of adding this feature to the Web Platform does not outweigh the additional complexity, and the cost of breaking one of the fundamental assumptions of CSS.
Comment by @cbiesinger May 24, 2021 (See Github)
We are proposing a change to this API to reduce the "side-effects from a property that no longer applies" issue here: https://github.com/w3c/csswg-drafts/issues/6308
If agreed to by the CSSWG, the scope of that issue will be much lower.
We consider it a huge benefit of this feature that no JavaScript code is required to get faster rendering while maintaining reasonable scrollbar behavior. It is difficult to write JavaScript code that works with arbitrary websites, because there is no good/efficient way to find elements to which contain-intrinsic-size
was applied. It also increases the barrier for entry to use this feature, from just applying a couple of CSS properties to having to find a "polyfill" or writing code yourself.
cc @chrishtr in case he has further input.
Discussed
May 31, 2021 (See Github)
Dan: punted to the plenary
Discussed
Aug 30, 2021 (See Github)
Dan: marked as proposed closing. On 24th May they said they're proposing a change, if agreed the scope of the issue will be much lower. Sounds like a change in scope and this issue is no longer relevant?
Rossen: I think we already discussed it and resolved. Based on our discussion end of May in CSS wg - we've resolved common visibility auto - that was one of the feedbacks that started this conversation... I don't see what else here is needed to continue to talk about.
Dan: we can close this?
Rossen: yeah. User benefit will be pretty great. Reduces need for javascript tricks people were using. This suite of capabilities is coming along pretty nicely. This is just a small addition to overall capabilities. we should not hold back on it.
Dan: We will close at the plenary.
Discussed
Sep 1, 2021 (See Github)
Dan: not much since may...
Rossen: we have a css wg resolution a couple of days after the last comment which constrains ... to auto matches only... by virtue of doing that we are scoping its effect quite a bit. So that part is fine. That was one of the points raised initially by ..? Some of it started from Lea's feedback. We have a good resolution on that issue.
Dan: can we close? if they've taken on board our feedback in their design. Do we have further objections? Can we live with it? And/or is there additional work going on in css so it doesn't need to be on TAG's docket?
Rossen: Definitely work going on. in terms of capability..
Dan: there's no privacy and security section. They say there's no need.. have we addressed that previously?
Rossen: I don't think so
Dan: is there some kind of privacy aspect?
Rossen: i don't see how
Lea: they've reduced the cases that violate CSS reactivity but it's still violating it part of the time.. philosophical purity is at the bottom of our priorties so if authors really want this and it's really needed then I guess it shold be fine. I don't like it but.. whatever.
Rossen: essentially this is a broader effort to reduce the overall resource loading during initial loads, there was an umbrella feature called ... where you don't have the content as part of the layout and rendering, but if you search for something with ctrl+f you actually will force the content to get populated and you will get from a user pov what you would have had anyway, however ..
Dan: if something only partially loads, like article text?
Rossen: right, you have loaded your content but you're not necessarily building the rendering part for it, you've parsed it and have the content and you can search it, might do initial layout for it, this is where thesee things are coming into play, the sizes for things, arranged that way, scrollbar has the size it would if laid out normally, but it's not rendered. Now when you go to search and for example scroll into view now the implementation needs to catch up and make sure what's in front of hte user is not a bunch of blanks. This is this whole feature. It had some weird name. This is part of it where the intrinsic size is for an image which is not rasterized and decoded yet, so you don't know what the intrinsic size of the image is
Dan: all aimed at faster page load?
Rossen: yes. And improve other thigs like battery life, memory footprint, cpu etc. Benefits for sure. But these are UA performance optimizations targeted features
Dan: lea what's your objection?
Lea: same objection that we have discussed in the past and gave as feedback - that css has always been this nice reactive language hin which things apply and stop applying without side effects. No ordered steps, current state is always a function of what is currently applying. Value in that simplicity. Last remembered state introduced here breaks this fundamental assumption. First css feature to break this, introducing side effects that persist after certain state has stopped applying introduces state that is not inspectable and has no obvious cause. But it's a philosophical objection.
Dan: I see.
Lea: breaks one of the assumptions of CSS. It is about authors - this is an assumption authors could make, whereas now thye have to take side effects into account. I don't want to stop a feature that is going to help authors
Rossen: users more than authors. From a tooling pov the simplicity that you were referring to also is a huge help to tooling. WYSIWYG developers.
Lea: I hadn't even thought about wysiwyg. Yeah. Also given it works in that way I'm not sure what is the benefit over a js library. that's exactly what a js does, remembers th elast state. Seems the main benefit of this is avoiding including a js library. The drawback is that it breaks one of the very fundamental design principles of css
Dan: you say the theoretical purity is ..
Lea: is it theoretical purity?
Dan: not if that's a principle that has all of these other benefits for developers and for the platform and tools. It's not theoretical purity, it's more.. purity.
Lea: I don't want to stop progress because of purity
Rossen: not about stopping progress, it's about whether or not the language constructs are invalidated
Dan: if other things make that assumptions, tools and stuff that processes css or that authors css makes that assumption and that assumption is broken by this thing.. the feedback from someone else - is that the side effect introduced does not persist after the property has stopped applying. Does that mean there's no side effect at all?
Rossen: well. after the property has stopped applying. You have to ask - what is that 'after' point? If the property applies at a particular frame, when all of the stylesheet and everything is calculated, then this is consistent with css. The effect of the property here is based on some user action, scroll things into view etc..
Dan: if there's something to push back on from a purity perspective we're definitely the ones to do it. We shouldn't pull back from that unless we think they are willing to clarify the design or change the design so it does not have this property
Lea: where do you see this quote?
Dan: in comment from 28th April.
Lea: a different property.. if contain intrinsic size auto is applying, the size is remembered for as long as content visibility auto is applied as well. If content visibilty auto is removed the ua forgets about the size. So there is a side effect when contains intrinsic size auto is removed
Dan: why don't we clarify that? I'm sympathetic to the use case of faster rendering
Lea: that's why I'm saying I'm not sure we should stall progress
Dan: worth continuing to raise the issue. There are side effects to changing this side effects thing. there are unintended consequences where if you change a precept that everyone working in this space knows and agrees to then there are the possibility of unintended consequences
Lea: we said they're breaking the princiople 100% of the time and they made a change so they're breaking it 30% of the time.. but if they're breaking it even 1% of the time it's no longer a universal assumption. Every tool that processes css now needs to take that into account, this edge case, this different behaviour
Dan: that needs to be written down in our feedback.
Lea: I can write a comment
Comment by @LeaVerou Sep 17, 2021 (See Github)
We looked at this again in our Gethen virtual f2f meeting.
While reducing the need for JS libraries and improving performance is definitely a goal we sympathize with, we are still concerned that this feature breaks one of the fundamental design principles of CSS, one that has been established for over twenty years. Breaking this assumption is not only confusing for authors, but has the potential to break tooling (e.g. WYSIWYG editors). While the new iteration reduces the cases where the side effects apply to when content-visibility: auto
also applies, it is still introducing side effects and uninspectable state.
If side effects are truly the only way to solve this problem, have you explored solving the problem with a JS API instead?
Discussed
Sep 20, 2021 (See Github)
Lea: I didn't see a response
Dan: wait more
Comment by @cbiesinger Sep 20, 2021 (See Github)
Thanks for the feedback!
TL;DR of the below: we think this feature is best viewed as a UA default behavior triggered by CSS, not a side-effect of CSS algorithms; there is precedent in features such as scrolling.
Full version:
After your latest comment, we thought some more about the issue of side-effects, and how to express it in some other way such as JS.
Regarding JS: as we mentioned previously, the feature can be polyfilled via a ResizeObserver, but we think it is (a) too expensive/difficult for developers (especially CSS-oriented developers) to be expected to reliably achieve, and (b) something almost all developers using content-visibility: auto would want (developer feedback from multiple partners has confirmed this).
We don’t think this should be viewed as a side-effect of a CSS algorithm (which we agree is a bad thing generally), but as a UA default behavior. Compare it with scrolling: scrolling is a super complicated UA default behavior that is triggered by CSS via overflow:scroll
, and has lots of built-in behaviors that have visual side-effects, such as scrollbar gutters, scroll offsets and so on.
This feature should be viewed similarly - it’s a thing that developers want to do and can potentially do themselves, but there is enough efficiency/convenience/defaults-work-well value that it makes sense for the UA to provide the functionality as a built-in.
Note that the feature is carefully specified to happen at ResizeObserver timing, so there is no magic implementation advantage of the browser over script. The only magic thing about this feature is where it stores the cached intrinsic size. Conceptually it stores it on a property of Element objects (and that’s exactly what the Chromium implementation does). But we don’t propose exposing that as a JS property (analogous to scrollTop
) to web developers at this time, nor do we propose exposing an event (analogous to scroll
) that can allow preventDefault
. If there were demand for such features we could expose them in the future (https://github.com/WICG/display-locking/issues/112).
Discussed
Oct 25, 2021 (See Github)
Dan: very fundamental CSS issue about side effects...
Lea: they do make a good point about scrollbars.
Rossen: christian basically says you can do this already with scrolling?
Lea: well we can't say if it's a fundamental rule of css if scrollbars also have a similar behaviour.
Rossen: I see christian's point. he's technically correct but the side effects we're talking about here that have the negative behaviour to users -
Lea: element has style that is not a function of the current state.
Dan: [use of the word magic...]
Lea: magic - when behaviour cannot be explained with code or complex heuristics...
Hadley: It usually means we don't understand it. Or there are people who aren't good enough to understand it.
Rossen: or when it's too big to fit in a paragraph...
Rossen: not sure ... I am very familiar with where they're coming from ... it's something we did many years ago in IE9 - predict sizes of media - doing your layout. Approx size, don't have to do a lot of compute .. saved a ton of battery and CPU - and then when you load them and you're close then the user sees no [movement]. From that PoV I sympathize.. and it's generalized. So you can create a wireframe of layout that can then be filled in... Does it have side effetcs? it could if you get it wrong. glitches of re-layout. I convinced myself that this is OK.
Peter: in general that style or layout state is left over from a previous algo is confusing - on the other hand I can think of some situations where we have to go there eventually. I'm OK with this.
Rossen: was curious if this has side effects to transitions in animations...
Dan: set to proposed closed?
Rossen: sounds ok.
Rossen: I will leave the comment.
Comment by @atanassov Oct 27, 2021 (See Github)
@cbiesinger, thank you for taking the time to reevaluate your proposal and other options. I agree that correlating with UA/scrollbar behavior is the right way to reason about this feature. With that in mind, the overall benefit to users in terms of perf/power savings is potentially significant thus I support it. The downside of the feature is that users can experience "popping" of layout as content loads and sizes changes from remembered
to something else. This is not great but reality is that users are conditioned to largely ignore that today due to infinite scrollers and content being loaded based on scrolling.
One questions I couldn't answer myself is what is the affect to transitions and animations. The current spec behavior defines computed
value as the starting point, which is the initial
value and not the remembered
value. Wouldn't this introduce a lot of discontinuity? Do you have any implementation experience that could suggest how glitchy are these?
Comment by @cbiesinger Nov 1, 2021 (See Github)
Thanks for the response, @atanassov . Are you concerned about a transition from contain-intrinsic-size: auto 1px
to contain-intrinsic-size: 2px
? For auto to non-auto (or vice versa), we consider those as incompatible and just flip at 50%, so it shouldn't make a difference which one we pick there. For auto 1px
to auto 2px
it won't matter because we'll just end up using auto in both cases.
cc @lilles @flackr in case they have any input.
Comment by @flackr Nov 1, 2021 (See Github)
Just to add on to this, treating auto as non-interpolable with non-auto values is the same as for other length properties which can be auto. Similarly auto -> auto is not a transition as they are the same value.
Discussed
Nov 8, 2021 (See Github)
Rossen: i think their answer to my question is these are non-transitional values. It is what it is.. they still need to make that more clear in the spec, otherwise they're not introducing anything necssarily new here in terms of transtions and animations, so from that point of view I think the feedback is to update the spec. Now the rest of this seems to be going towards closure.. I'll respond, can mark as proposed close
Peter: close in plenary?
Rossen: if they reply by then.
Peter: I'm concerned about making it non-transitional.. bad develoer experience
Rossen: auto is almost always non transitional. Don't know of cases where transitioning from or to auto is transitional
Peter: cases where it could be, but complicated
Rossen: I'm not going to ask them to invent better css out of that feature
Peter: fair enough
Comment by @atanassov Nov 8, 2021 (See Github)
Sounds reasonable and consistent with any other to/from auto
transition. Please consider adding a note in the spec in order to make that easier to understand for authors. It wasn't obvious to me, though it was the anticipated answer knowing how the rest of CSS works :)
Comment by @atanassov Nov 10, 2021 (See Github)
We did another quick pass of the issue during our plenary meeting today. The overall shape of the feature and use cases addressed are a good fit to CSS and web, thus we are happy to close the review.
One remaining ask continues to be about the transitions/animation note we'd like to see added to the spec.
Thank you for working with us and good luck with finishing the work with the CSSWG.
OpenedApr 16, 2021
Ya ya yawm TAG!
I'm requesting a TAG review of contain-intrinsic-size: auto, and converting to a shorthand property.
This adds an "auto" keyword to contain-intrinsic-size, which lets the rendering engine remember the last used size so that the author does not have to guess correctly (with a fallback size if the element was never laid out without size containment). Also, longhand properties were added, including logical axes: contain-intrinsic-width, contain-intrinsic-height, contain-intrinsic-block-size, contain-intrinsic-inline-size
Further details:
You should also know that...
[please tell us anything you think is relevant to this review]
We'd prefer the TAG provide feedback as (please delete all but the desired option):
🐛 open issues in our GitHub repo for each point of feedback