w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 666 forks source link

[css-overflow-5] Improve active marker calculation #10917

Open flackr opened 1 month ago

flackr commented 1 month ago

Currently the active scroll marker is determined by finding the target which is scrolled to or before the current scroll position. However, this means that even when the next section is 90%+ visible until it reaches the top of the scrollport (or it's scroll aligned position) the active marker does not update to this section. See https://flackr.github.io/carousel/examples/scroll-marker/scrolltarget/ for a demo of this behavior.

Instead, I propose we have the active marker calculated using logic similar to how snap areas are selected where we will select the next section if the previous target is above its desired scroll alignment and the next one is more than half-way to being aligned.

This could be analogous to snap areas where we create a virtual snap area from the start of one scroll target to the start of the next, however unlike snap areas we still want to strongly consider the previous if the next one is not yet sufficiently in view. E.g. if you're scrolled halfway through section 1 even though the target (the header) is scrolled above the viewport you should still be considered to be in section 1 until section 2 is mostly in view.

flackr commented 1 month ago

We need to balance for uses where scroll marker targets may be

Proposal, when deciding whether we should select the next item, we do so when:

  1. We are past the ideal alignment of the previous (current algorithm), and
  2. The next marker target intersects the viewport, and
  3. The distance from the previous item's aligned scroll position to the next item's aligned scroll position (capped to one scrollport to not eagerly choose the next item) is more than twice than the distance to the next item being aligned.

Note that we unfortunately cannot use the exact same logic as snap areas. Since the target may only be the header of the entire section, we should consider the effective target to be everything from the first target being aligned to the next target being aligned. We could consider re-using the snap logic using this virtual area.

kizu commented 1 month ago

The proposed algorithm sounds good at the first glance. I recently implemented something similar to it in my blog (https://blog.kizu.dev/captured-custom-properties/ for example, using scroll-driven animations, so works only in Chrome for now, source CSS behind it). I am using an inset: 50% with the “markers” on headers, which seems to work better than any of my other attempts to do so.

css-meeting-bot commented 1 month ago

The CSS Working Group just discussed [css-overflow-5] Improve active marker calculation, and agreed to the following:

The full IRC log of that discussion <fantasai> s/Topic: Pub/Subtopic: Pub/
<fantasai> flackr: Currently in spec we select the marker whose target has scrolled at least as far as, if not further than,
<fantasai> flackr: but this means that as you scroll into next section, doesn't become active until it hits its aligned position
<fantasai> flackr: e.g. at top of viewport
<fantasai> flackr: similarly for carousel use cases, doesn't switch until next item is completely scrolled into view
<fantasai> flackr: [demo of lag in the scroll marker]
<fantasai> flackr: proposing more intelligent selection, finds next marker when it's closer to the viewport
<fantasai> flackr: rough proposed algorithm in the spec
<fantasai> flackr: details are nuanced, because don't need to be larger than scrollport
<florian> q+
<fantasai> flackr: for example distance from one heading to another
<miriam> q+
<fantasai> flackr: so wanted to take a resolution that yes, we make changes
<fantasai> flackr: similar to if we were snapping, would change to the new thing
<fantasai> flackr: not quite the same because scroll targets could be headings, not the entire section
<fantasai> flackr: so this is why we can't share exactly the scroll snap properties
<Rossen6> ack fantasai
<dholbert> fantasai: haven't thought through it in detail, but going in this direction does make sense
<kizu> q+
<fantasai> florian: Makese sense to go in this direction, but wonder if it shouldn't be a quality of implementation issue
<Rossen6> ack florian
<fantasai> florian: Can imagine variants
<fantasai> florian: e.g. if you are scrolling towards one vs (missed)
<fantasai> florian: may be some nuances
<fantasai> flackr: could keep it open for now
<fantasai> flackr: but in any case what you're proposing shouldn't be disalowed
<fantasai> miriam: there's some advantage to predictability
<fantasai> miriam: so I have some concerns about being too clever with it
<fantasai> miriam: which makes me lean other way from Florian, maybe better to keep it simple and consistent across browsers
<fantasai> miriam: definitely I don't trust the concept of "closer" because one heading can be much closer when still not in th viewport
<fantasai> miriam: it has to be a lot more clever than that
<fantasai> flackr: cleverer thing written in the issue
<fantasai> miriam: don't want to lose simple and predictable
<florian> q?
<florian> q+
<Rossen6> ack miriam
<fantasai> flackr: would it make sense to come back with a concrete somewhat clever proposal and see if we can agree on it?
<fantasai> kizu: what's proposed there in the issue makes sense
<fantasai> kizu: this is close to my latest implementation of this
<kizu> https://github.com/w3c/csswg-drafts/issues/10917#issuecomment-2380087937
<fantasai> kizu: [describes his latest marvel of CSS engineering]
<fantasai> kizu: in Chrome you can see how it works
<fantasai> kizu: I really like this, it's very in line with what flackr wrote
<fantasai> kizu: but would be nice to see exactly what's proposed
<Rossen6> ack *
<Rossen6> ack kizu
<fantasai> flackr: for discussion with mia, goes both ways
<Rossen6> ack florian
<fantasai> s/flackr/florian/
<fantasai> florian: to the extent people will build on it, better to have more predictability
<fantasai> florian: on the other hand this is in UX space, and trade-offs in one UA might differe from other UA, possibly depending on input modalities
<fantasai> florian: I would expect UAs to fine-tune this, which might result in different answers
<fantasai> florian: so providing flexibility seems useful
<fantasai> miriam: less about building on top and, already there are use cases where I would want different ansewrs
<fantasai> miriam: if I was being clever
<fantasai> miriam: I would come up with a different clever algo for ToC than for carousel slider
<fantasai> miriam: so that makes me mistrust the idea that we can find one clever option that will work across use cases
<fantasai> flackr: could add for a snapping carousel, if using scroll position that you would land on after snapping
<fantasai> flackr: so this exampe with carousel is slightly contrived, since I'm holding downt the scrolling mechanism
<fantasai> flackr: but in any free-flowing content, this problem is as I showed you
<Rossen6> ack fantasai
<dholbert> fantasai: I don't remember what's in the spec, but if there are constraints we are sure of, e.g. this should definitely be the scroll marker, we should document those in the spec
<dholbert> fantasai: for cases where we need to decide the next action, we/miriam shoudl document some use cases
<dholbert> fantasai: flackr should perhaps document the parameters that are worth reasoning about when comparing strategies here
<dholbert> fantasai: once we have the examples for these use cases, we can decide which direction to go
<dholbert> flackr: what sorts of examples might be handy?
<dholbert> fantasai: e.g. "if you're an implementor and you're looking at these two cases, here's how you might write an algorithm to land on the right thing"
<dholbert> fantasai: maybe with an illustration, but that's optional
<fantasai> flackr: Propose resolve as keep spec as-is, but miriam adds use cases, flackr adds example algorithms ...
<fantasai> flackr: but might require resolving that there's flexibility in the spec
<fantasai> flackr: so should we resolve on flexibility in the spec?
<dholbert> fantasai: there's some flexibility, and some non-flexibility
<dholbert> fantasai: there are cases when e.g. you'd land on a thing where it's obvious you need to pick that scroll marker
<fantasai> flackr: I think for this demo should relax it a bit
<florian> q?
<fantasai> flackr: so need to remove the explicit algorithm about finding the thing before the current scroll position and use more open language
<fantasai> flackr: similar to snap point selection
<florian> +1
<fantasai> PROPOSED: Relax spec for less definitive cases, miriam to add use cases to issue, flackr to write possible algorithm(s) as examples
<fantasai> RESOLVED: Relax spec for less definitive cases, miriam to add use cases to issue, flackr to write possible algorithm(s) as examples