Skip to content

[css-scroll-snap] Snap direction needed for snap-overflow #5123

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

Open
guidobouman opened this issue May 27, 2020 · 10 comments
Open

[css-scroll-snap] Snap direction needed for snap-overflow #5123

guidobouman opened this issue May 27, 2020 · 10 comments

Comments

@guidobouman
Copy link

guidobouman commented May 27, 2020

The issue

When snapping to items that are larger than the viewport, the spec declares that the user must be able to freely scroll while the edges of the item do not yet meet the edges of the scroll container. See https://www.w3.org/TR/css-scroll-snap-1/#snap-overflow for details.

But what happens when you always want a scroll container to snap to the first edge of the target item after a scroll action? Right now, according to the spec, a scroll container always snaps to the specified edge. Regardless of the direction the user is scrolling in.

Demo of the problem:

Scroll down and back up in small steps to replicate the unwanted behaviour.

To clarify, I would like to:

  • Snap to top when a user scrolls down
  • Snap to bottom to user scroll up

Expected behaviour:

Proposed solution

This problem can be addressed with new values on scroll-snap-align. One for each edge a scroll container can snap to. Looking from the perspective of the scroll direction: the start edge or the end edge. Center is center regardless of the scroll direction.

Considered options

First idea:

  • nearest-edge
  • farthest-edge

Alternative, more explicit:

  • scroll-direction-start
  • scroll-direction-end

Shorter alternative:

  • direction-start
  • direction-end

Alternative solution

Introduce a new key scroll-snap-overscroll-behaviour with the values auto & contain. Where contain would implement this same behaviour. But that might break the expectations a developer might have for scroll-snap-align, and create conflicting rules.


Disclaimer: I'm the author of PanelSnap, and would like my package to become obsolete.

@guidobouman guidobouman changed the title [css-scroll-snap] Snap needed on snap-overflow [css-scroll-snap] Snap direction needed on snap-overflow May 28, 2020
@guidobouman guidobouman changed the title [css-scroll-snap] Snap direction needed on snap-overflow [css-scroll-snap] Snap direction needed for snap-overflow May 29, 2020
@guidobouman
Copy link
Author

As spec authors, what do @ChumpChief @tabatkins and/or @fantasai think?

@fantasai
Copy link
Collaborator

Adding a nearest-edge value to scroll-snap-align makes sense to me. @majido What do you think?

@guidobouman
Copy link
Author

If you need anything, I would love to help out.

@majido
Copy link
Contributor

majido commented Nov 11, 2020

/cc @flackr

I don't fully understand how this relates to "larger than the viewport".

To clarify, I would like to:

  • Snap to top when a user scrolls down
  • Snap to bottom to user scroll up

So if I read this correctly the desire is to have more control over which snap alignment the browser selects. In particular, you want to ensure the alignment in the direction of user scroll is selected (or preferred?).

That is a reasonable thing to have IMO.

Some notes:

  • I don't think this maps to the nearest-edge as @fantasai is suggesting. It is more like edge-in-the-scroll-direction
  • The term scroll direction is fuzzy. For example what is the scroll direction if user scroll down a lot and up a little bit in the same gesture? Chromium has some heuristic to infer a direction but not every scroll gesture has a direction. So I take it you want these new behavior to apply to gesture with direction.
  • FWIW, in chromium we do prefer the snap point in the scroll direction for subset of scroll gestures (those with clear direction) but there may be bugs and does not apply if we don't consider it directional. (details)
  • This is minor but in my mind this falls more into 6.2 choosing snap position. In that we have a preference for a particular selection as opposed to restricting valid snap positions. My mental model has been that scroll-snap-align defined what is valid. So it feels to me that we should not use scroll-snap-align property and instead add a new one similar to what we did with scroll-snap-stop.
  • Also what is considered valid snap position currently does not depend on scroll gesture which means it can be pre-calculated and cached to be used across multiple scroll gesture (which Chromium does). At the moment only the position selection algorithm depends on the particular scroll gesture (position, direction etc.). I think we should keep it that way

In any case flackr@ is the right person to look into this and give further implementation advice from Chromium side.

@fantasai
Copy link
Collaborator

@majido I think you are thinking about how to choose which snap position considering multiple elements on the page, whereas @guidobouman afaict is talking about snapping to a single element that happens to be larger than the viewport.

For example, consider a section that is three screenfuls tall. The desired behavior is that when you scroll down, the UA snaps to the top edge, but when scrolling up snaps to the bottom edge -- in other words, to the nearest edge. Currently, we can decide to always snap to the bottom edge or always to the top edge, but not the nearest one. See the demos in the OP.

@tabatkins
Copy link
Member

Yeah, this is all about overlarge-area snapping, and it makes a ton of sense; our current behavior, I'd argue, is pretty hostile. Maybe we should just make it always the behavior for overlarge elements, rather than forcing people to recognize when it might matter and remember to apply the nearest-edge value? (And part of the reason for the overlarge-area behavior is precisely because authors can't always predict whether an element will be larger than the viewport or not.)

I also think that we don't have a good reason to want the "nearest-edge" behavior for non-overly-large elements. If a small element was given "scroll-snap-align: nearest-edge", then it would snap its top edge to the top of the screen and its bottom edge to the bottom fo the screen, and I think that's usually not what's doing to be desired here.


As an aside, @majid, the codepen in the OP is showing off some examples that are actually trapping my arrow-based scrolls at times. In particular, the first example reproducibly traps me on element 2 when I'm arrow-scrolling down to it; I can arrow back up, but can't arrow down any further until I adjust the scroll some other way first, like clicking down on my scroll wheel. PgDn scrolling continues to work, tho. I get similar trapping on the sideways examples, tho for some of them its element 3 that traps me.

@guidobouman
Copy link
Author

To snap to the "nearest" or "first" edge for larger-than-viewport elements by default makes a lot of sense, if we ignore backwards compatibility. Except, this falls apart when an author provides scroll-snap-align: end;, what would happen then? Would scroll-snap-align just cease to work for those elements?

Take the most explicit values from my proposed solution: scroll-direction-start & scroll-direction-end. I can imagine a sticky header or sticky footer, depending on the direction you scroll in. Even when the elements are smaller than the viewport, the possible values still make sense.

To come back to @majido's comments:

  • I think the last detected scroll direction (swipe gesture on touchpad, keyboard keys, computation scroll etc.) should be leading for this behaviour.
  • And regarding the cache: As we're in a 2D space, the problem space is finite. There are two (probably precomputed) sets of possible options to switch between when the scroll direction changes. I don't think that will be the biggest performance implication, right?

About the aside:
The codepen examples are native scroll-snap implementations. I think an arrow navigation trap should not be intended. Browser (Chromium?) bug?

@guidobouman
Copy link
Author

@tabatkins @fantasai Can I do anything to help move this forward?

@guidobouman
Copy link
Author

guidobouman commented Oct 13, 2021

Friendly reminder. ☝️

PS: If this is not the right medium to move a discussion like this forward, what would be a better place?

@fantasai fantasai added css-scroll-snap-1 Current Work and removed css-scroll-snap-1 Current Work labels Feb 14, 2023
@guidobouman
Copy link
Author

It seems like Chromium-based browsers now apply the corrected behavior after only a small wording change in the spec. 🥳

Not sure when it was fixed in Chromium, anyone has a changelog ticket? This is a great step forward, now I can ask other browser vendors also fix the behavior.

PS: Does anyone know of a way to detect the support during runtime? (Want to make my plugin yield to the browser-native scroll-snap when possible)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants