Re: [csswg-drafts] [css-contain] `scroll-state(stuck)` CQs can easily cause flickering that is very hard to work around (#13898)

The CSS Working Group just discussed ``[css-contain] `scroll-state(stuck)` CQs can easily cause flickering that is very hard to work around``.

<details><summary>The full IRC log of that discussion</summary>
&lt;TabAtkins> lea: similar in :hover it's usually an author mistake<br>
&lt;TabAtkins> lea: but here, i spent a few hours trying to work around it, and couldn't find a good one<br>
&lt;TabAtkins> lea: all the workarounds only somewhat work, or they fix in only one direction, etc<br>
&lt;flackr> q+<br>
&lt;kizu> q+<br>
&lt;TabAtkins> bramus: this def reminded me of :hover, but also scroll-driven animations<br>
&lt;TabAtkins> bramus: if your animation affects layout, it can change your animation progress<br>
&lt;TabAtkins> bramus: so this seems to be working as intended, stuff recalcs<br>
&lt;TabAtkins> bramus: Tab chimed in tho that there might be a spec fix<br>
&lt;lea> q?<br>
&lt;lea> scribe+<br>
&lt;lea> q+<br>
&lt;lea> TabAtkins: in Lea's case, turning off scroll anchoring helps, when it gets smaller it shifts up and we adjust the scroll position, disabling scroll anchoring does fix it for this particular case<br>
&lt;lea> TabAtkins: it doesn't fix it in general. E.g. if you move the headings to the bottom and have them be bottom sticky you get the same issue for the same reason and overflow-anchor won't fix it<br>
&lt;lea> TabAtkins: and that one is actually unsolvable, no way around it<br>
&lt;lea> TabAtkins: I don't know for sure how we want to solve this. My idea is similar to contain-intrinsic-size to have a "last remembered size"<br>
&lt;lea> TabAtkins: we can do something similar here in theory, have them remember their last geometry while they are stuck<br>
&lt;lea> TabAtkins: we just layout as normal and just project the new thing so you have no movement in the page when something becomes sticky<br>
&lt;lea> TabAtkins: because this is fundamentally a circular geometry problem<br>
&lt;lea> TabAtkins: don't see a way around it without it doing something like that<br>
&lt;astearns> ack flackr<br>
&lt;TabAtkins> flackr: i'm concerned about "last stuck size" being stale<br>
&lt;TabAtkins> flackr: if anything changes about the page while stuck, your unstuck bounds could be different<br>
&lt;lea> TabAtkins: I presumably would forget it if the containing block changes<br>
&lt;TabAtkins> flackr: one alt is to treat this like size cqs, where we force layout containment, so style change can't cause the layout change. but that makes it harder to do some of these use cases<br>
&lt;astearns> ack kizu<br>
&lt;TabAtkins> kizu: +1 to try and solve this.  i hit this exact case<br>
&lt;TabAtkins> kizu: the workaround was solely to use transforms. pretty awkward but it works<br>
&lt;TabAtkins> kizu: if we were to solve it, containment woudl be one way. remembering previous size might be good to ahve in general, for other use-cases<br>
&lt;TabAtkins> kizu: various reasons to want to render something twice to compute some stuff<br>
&lt;TabAtkins> kizu: so there are many use-cases that could benefit from this idea<br>
&lt;astearns> q+<br>
&lt;miriam> q+<br>
&lt;TabAtkins> kizu: for this specific case, maybe containment would be a good thing to mention in the specs, at least<br>
&lt;TabAtkins> (size containment, in particular, being the most relevant one)<br>
&lt;TabAtkins> kizu: so you want a fixed heading, etc<br>
&lt;astearns> ack lea<br>
&lt;TabAtkins> lea: one thing i forgot to mention is a particular argument is "dont' do that"<br>
&lt;TabAtkins> lea: dont' think that's viable, so many use-cases want to affect the box model. basic common use-case is to make the element smaller and more discrete, now that it's taking up viewport space<br>
&lt;TabAtkins> lea: also block size containment is more diffficult for authors than inline<br>
&lt;TabAtkins> lea: unless maybe it's magic and only triggers when stuck, that's just what TAb is discussing<br>
&lt;TabAtkins> lea: also, it seems like stuck queries are on the stuck element, while the other queries are on the scroller<br>
&lt;bramus> Multiple elements can be stuck at the same time, though<br>
&lt;TabAtkins> lea: would it make sense to put the stuck query on the ancestor? then you could style the element itself that's stuck<br>
&lt;TabAtkins> yeah that's what i was gonna say too, doesn't work<br>
&lt;futhark> q+<br>
&lt;TabAtkins> astearns: we shoudl probably come u pwith something for this particular problem. wary of making a more general mechanism without motivating use-cases. not against it, it's just big and needs justification<br>
&lt;astearns> ack astearns<br>
&lt;astearns> ack miriam<br>
&lt;TabAtkins> miriam: i think i mostly agree with lea's points<br>
&lt;TabAtkins> miriam: to me it seems like more isolation/restrictions is more damaging to the use-cases than TAb's proposal of remembering unstuck size<br>
&lt;TabAtkins> miriam: that's probably what i expected the behavior to be, actually<br>
&lt;astearns> ack futhark<br>
&lt;TabAtkins> futhark: commenting on why we're querying the stuck element, not the scorller<br>
&lt;flackr> q+<br>
&lt;TabAtkins> futhark: you want to know which element is stuck, can have multiple<br>
&lt;TabAtkins> futhark: so what's causing the issue is that the layout changes and can affect the stickiness<br>
&lt;TabAtkins> futhark: so remembering the size so nothing changes does sound like a good thing<br>
&lt;astearns> ack flackr<br>
&lt;TabAtkins> (i propose we take back to the issue for details)<br>
&lt;TabAtkins> flackr: i am concerned that just "remember last size" is easily stale and has corner cases<br>
&lt;TabAtkins> flackr: if you change content, last size is now invalid<br>
&lt;TabAtkins> flackr: if you re-resolve, you have the double computation problem<br>
&lt;TabAtkins> flackr: for each sticky query you'd need to compute both stuck and unstuck size<br>
&lt;lea> Transforms are really not a good option here<br>
&lt;kizu> Certain authors will render two elements, hide one of them, measure it with SDA, and apply the value to an absolutely-positioned one, just saying :D<br>
&lt;TabAtkins> flackr: transforms are always okay because they dont' change the layout box. it's not you should never change the size, just you shoudl never change the layout constraints that make it stuck<br>
&lt;lea> Try to implement the example I sent with transforms<br>
&lt;TabAtkins> flackr: i'm inclined to say that some of these cases are dev error<br>
&lt;TabAtkins> flackr: i think the default scroll anchoring we're doing now is clearly wrong, maybe we can fix that<br>
&lt;smfr> q+<br>
&lt;astearns> ack smfr<br>
&lt;lea> q+<br>
&lt;TabAtkins> (i think fixing scroll-anchoring, to make the common top-stuck case work, is gonna be a nice 80% solution for now)<br>
&lt;lea> smfr: this was included in the OP as one of the workarounds<br>
&lt;bramus> (or a new `position: fixed-like-sticky` 😬<br>
&lt;TabAtkins> smfr: one way to fix is to put an element between the sticky and its contnets<br>
&lt;TabAtkins> smfr: fr4om the author, or a pseudo<br>
&lt;futhark> q+<br>
&lt;TabAtkins> smfr: and in the stuck state they could change the height of the wrapper...<br>
&lt;TabAtkins> smfr: maybe tricky with hit testing, etc. but a possibility<br>
&lt;astearns> zakim, close queue<br>
&lt;Zakim> ok, astearns, the speaker queue is closed<br>
&lt;astearns> ack lea<br>
&lt;TabAtkins> lea: re: using transforms, if you do it in practice for the example i shaed, it doesn't really work<br>
&lt;ydaniv> what smfr suggested, like a pseudo layout box wrapper is very interesting!<br>
&lt;smfr> transforms will squish text<br>
&lt;astearns> kizu also said that transforms aren’t a great solution, I think<br>
&lt;kizu> I meant transform on an inner element, with the outer staying the same<br>
&lt;TabAtkins> lea: [lists squishy problems with transforms]<br>
&lt;TabAtkins> lea: the additional element solution (counting as removed height) is an example in the OP. there's downsides listed there<br>
&lt;TabAtkins> lea: it affects vertical space when scrolling back, hard to find a good height, have to set pointer-events:none, etc<br>
&lt;TabAtkins> lea: currently it also eats ::before/after<br>
&lt;TabAtkins> lea: and i push back on this being a dev error, i wrote a common case and then spent errors trying to fix<br>
&lt;TabAtkins> lea: in terms of "last remembered", wonder if it could help to specify what size is remembered... attach height to a name, use that explicitly<br>
&lt;TabAtkins> lea: might solve issues with us having to solve this implicitly<br>
&lt;kizu> `will-not-change: height padding`<br>
&lt;TabAtkins> futhark: similar concerns to Lea about wrapper elements<br>
&lt;TabAtkins> astearns: okay, take back to the issue. sounds like we want a solution to the problem<br>
&lt;TabAtkins> astearns: some concerns that a solution might have weird side effects, so let's work thru what we could possibly do.<br>
</details>


-- 
GitHub Notification of comment by css-meeting-bot
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/13898#issuecomment-4443147937 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 13 May 2026 16:25:21 UTC