Open DavMila opened 2 months ago
I thought of a possible option that would support a lot of the 2d cases fairly simply. We could scroll to every specified item in order, then if you combine this with nearest
behavior it will try to scroll to a position that includes all of the specified elements. Elements that are wider than the viewport (e.g. scrolling to a row in a table) won't move the horizontal position as its already fully in view and thus implicitly supports the scrolling to a specific row and column use case.
I also wonder if we should consider re-using scroll-snap-align
for this. We already use scroll-margin
and scroll-padding
to affect scrolling behaviors beyond snapping, it seems reasonable that we may want a scroll-align
which affects the alignment used for anchor scrolls or other scrolls even when not using scroll snapping.
great idea to leverage snap-align
, that way the scroll-start-target
when scrolled to can be positioned optimally 👍🏻
Some use cases to consider where multiple scroll start targets might be specified for a single scrolling container could be:
To address the use cases and resolve this issue as well as #8832, I propose the following:
Define scroll-align
, a generalized version of scroll-snap-align
that works outside of snap containers and possibly in snap containers without establishing a snap point. The former is currently a MAY in the spec:
If a page is navigated to a fragment that defines a target element (e.g. one that would be matched by :target, or the target of scrollIntoView()) ... the user agent must snap to one of that element’s snap positions if its nearest scroll container is a scroll snap container. The user agent may also do this even when the scroll container has scroll-snap-type: none.
This property should also accept nearest
values to allow specifying all of the ScrollLogicalPosition values of the scrollIntoView API. It may make sense for scroll snapping to support nearest
as well to support making items that snap such that they're not partially in view but don't have a particular affinity for aligning only on one side of the scrollport.
The combination of nearest
values in point 3 and attempting to scroll to multiple items in point 2 would provide a reasonable best-effort attempt to scroll all of the requested items into view while still ensuring that the first one (the current specified behavior) is in view at the end.
This property should also accept
nearest
values to allow specifying all of the ScrollLogicalPosition values of the scrollIntoView API. It may make sense for scroll snapping to supportnearest
as well to support making items that snap such that they're not partially in view but don't have a particular affinity for aligning only on one side of the scrollport.
This proposal makes sense to me overall but I could use some help clarifying the concept of "items that snap such that they're not partially in view but don't have a particular affinity for aligning only on one side of the scrollport." Is this similar to scrollIntoView's concept of nearest where if the element is already partially in view, no scrolling happens?
I could use some help clarifying the concept of "items that snap such that they're not partially in view but don't have a particular affinity for aligning only on one side of the scrollport." Is this similar to scrollIntoView's concept of nearest where if the element is already partially in view, no scrolling happens?
Yes, that is exactly right. scroll-snap-align: nearest
would try to snap the element to the start and end alignment so that the scroll does not rest in a position with the element partially clipped by the scrolling container.
Yes, that is exactly right. scroll-snap-align: nearest would try to snap the element to the start and end alignment so that the scroll does not rest in a position with the element partially clipped by the scrolling container.
Okay thanks, I think your proposal would be a great way to solve this. Shall we agenda+ this issue?
The CSS Working Group just discussed [css-scroll-snap-2] How should competing scroll-start-targets be resolved?
, and agreed to the following:
RESOLVED: When scroll-start-target targets multiple elements, scroll to each in reverse DOM order with text to specify priority is the first item
The scroll snap 2 spec says that when there are multiple elements that could be scroll-start-targets for a scroll container "user-agents should select the one which comes first in tree order".
Selecting the first element in tree-order seems like a natural way to resolve competition between multiple targets which would be scrolled to in one particular axis but is perhaps not as flexible as might be needed for the 2d case where an author wants to scroll to one item in one axis and another item in the other axis.
An alternative that might be more flexible would be to compute the intersection of the relevant scroll-start-targets in each axis (originally suggested by @flackr ). This could prove useful for the 2d case where an author has a table/grid and wishes to specify a row and a column as the scroll-start-target in the vertical and horizontal axes respectively (which was the main use case for having scroll-start-target set separate inline and block values, though that has since been removed from the spec). User agents could handle the case where none of the scroll-start-targets end up in the scrollport by giving preference to the scroll-start-target that is first in tree order or some other resolution mechanism or simply leave that for the author to avoid. Since the current scroll-start-target syntax (
scroll-start-target: [auto|none]
) takes only one value that should apply to both axes, this alternative raises the question of how to associate one scroll-start-target with a particular axis. I can think of 3 options for associating a scroll-start-target with an axis:scroll-snap-align
properties of the scroll-start-targets, first prioritizing the presence ofscroll-snap-align
and then tree order.scroll-start-target
a shorthand forscroll-start-target-{x,y,inline,block}
.Perhaps we could adopt the current spec as-is for the moment, i.e. pick the first-in-tree-order target and scroll to it in both axes, and leave more complicated syntax/logic for a future version of the spec?