w3c / csswg-drafts

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

CSS Snap Points: Event Model Missing #156

Open scottjehl opened 8 years ago

scottjehl commented 8 years ago

It would be useful if CSS Snap Points had an event model for events like say, snapstart, snapstop, and snapchange. Currently, we can listen for scroll events and try to simulate these events, but it's hard to pinpoint when a native snap starts and ends, as opposed to a user-driven scroll.

tabatkins commented 8 years ago

Yeah, def.

fantasai commented 8 years ago

Note: In the interest of wrapping up the existing set of functionality (which is well-specced and pretty much done), we're deferring the event model until a later level of CSS Scroll Snap.

pavelkornev commented 5 years ago

Up. @fantasai Isn't it time?

fantasai commented 5 years ago

@pavelkornev It is. I unfortunately don't have the expertise to draft something up, but I'm happy to accept proposals. :) They'd go into Level 2, but we can certainly start a draft as soon as there's something to put in it.

tunelinks commented 5 years ago

I believe if a user scrolls or shrinks their viewport the snap should move the scrollbar to the center so it can be more responsive. Please see this for example and move your scrollbar to another position and then shrink the browser. https://codepen.io/anon/pen/jRjpQv

jonjohnjohnson commented 5 years ago

@tunelinks your concerns are already handled in the spec with this language...

If the content or layout of the document changes (e.g. content is added, moved, deleted, resized) such that the content of a snapport changes, the UA must re-evaluate the resulting scroll position, and re-snap if required. If the scroll container was snapped before the content change and that same snap position still exists (e.g. its associated element was not deleted), the scroll container must be re-snapped to that same snap position after the content change. https://drafts.csswg.org/css-scroll-snap/#snap-strictness

Though implementors have yet to implement this logic. Chime in on filings like these to encourage implementation.

Also, your concern isn't exactly related to the original issue above.

DrummerHead commented 5 years ago

Is this what I need to know to make a spec proposal? Or is there more documentation?

frivoal commented 5 years ago

@DrummerHead, yes, that (and the things linked from it) is a good starting point. I would also add that it is usually recommended to be very explicit about the uses cases you are trying to solve with your proposal. A problem that is obvious to you may not always be obvious to others, and unless we all understand what it is that we're trying to solve, it can be hard to agree on the best way to solve it.

fantasai commented 5 years ago

@DrummerHead The TAG drafted an "explainer explainer", which is maybe a good starting point. But basically, a proposal to solve this needs to A) define some syntax, B) explain at least at a high level the expected behavior, and C) explain some of the use cases it solves, with some examples. It doesn't have to be super formal, just so long as it communicates those three things. :)

zeluspudding commented 4 years ago

C) explain some of the use cases it solves

Would the events api be the only way to build pagination for a slider (to indicate which slide I'm on)? I currently need this but am not aware of a way to extract the current dom's index using the current CSS Snap Scroll implementation (here's a codepen). .. this makes me think (in the mean time) that I have to revert to a javscript scroll slider? Is that true?

UPDATE Here's how I detect that a scroll has completed / update the current index. Not sure it's the best but it works.

SebastianZ commented 4 years ago

Just to get the ball rolling, here is how I imagine an event model for scroll snapping could look like:

Syntax

snapped event

Type: snapped Interface: SnapEvent Sync / Async: Sync Bubbles: Yes Trusted Targets: Element Cancelable: No Composed: Yes Default action: None Context (trusted events):

interface SnapEvent {
    readonly attribute EventTarget? relatedTarget = null;
    readonly attribute EventTarget scrollContainer;
    readonly attribute DOMString inlineSnapPosition;
    readonly attribute DOMString blockSnapPosition;
};

Expected behavior

The snapped event is dispatched on the scroll container after snapping happened at a snap position. This allows an author to know when snapping happened and what caused it.

Use cases

That's just a rough draft and I probably missed some use cases and things required to cover them. Also note that the snapped event defined here is triggered after snapping has happened, as I couldn't come up with use cases in which you'd want an event that is triggered before snapping. Though maybe there are cases in which you want to know beforehand when snapping will happen and maybe be able to cancel it.

So I encourage everyone to comment on this idea and come up with more use cases.

@scottjehl You mentioned three events, though I am not sure what snapstart and snapstop were meant to be for and when they should be triggered. I assume the snapped event I described is what you called snapchange.

Sebastian

frivoal commented 4 years ago

maybe there are cases in which you want to know beforehand when snapping will happen and maybe be able to cancel it.

I suspect it's better to leave this out (as you did) unless there are extremely compelling use cases for that. Having potentially blocking JS calls in the middle of scrolling tends make browser engineers very sad.

Other questions:

smfr commented 4 years ago

Proposals here should also keep in mind the proposed scrollend event: https://github.com/WICG/overscroll-scrollend-events

SebastianZ commented 4 years ago

Other questions:

  • Is your event supposed to be fired when the browser has landed on the snapped position and stopped moving, or as soon as it has decided on a snap position, even though it might still be moving towards it? (I think it's the former, but it's good to be clear)

When the browser has landed on the snapped position and stopped moving. The "decided on a snap position" case is probably meant by the snapstart event mentioned by @scottjehl.

  • If the user starts scrolling away from a snap point, but not very far, releases, and the browser snaps back to the same one, do we fire a new event because we resnapped, or not, because we effectively didn't leave the snappoint?

A new event should be fired. The author can distinguish this re-snapping by checking event.target === event.relatedTarget if necessary.

  • Same question as above, but with the user resizing the window rather than scrolling.

I tend to say yes for that case, because the snap position can change in that case. Not necessarily when the scroll container was already snapped before the change and is snapped to the same position after the resizing, as the spec. requires to re-snap at that position in that case. Though for consistency the event might also be triggered in that case.

  • Same question as above, but with the "resnapping" being triggered by a change in content / styling

Same as above.

  • If the snap position is continuously moving due to an animation or a transition, and the browser continuously tracking it, do we send a stream a events because we're continuously resnapping, or not because we never leave the snapped state?

As far as I can see, the specification currently doesn't define what happens for animations and transitions, i.e. whether snap positions are continuously adjusted or just when the animation or transition ends.

If the snapped state is never left and the scroll container stays snapped at the same snap position, I'd say no event should be fired.

Generally speaking, everytime the snapped state changes from "not snapped" to "snapped" a new snapped event should be fired.

Sebastian

SebastianZ commented 4 years ago

Proposals here should also keep in mind the proposed scrollend event: https://github.com/WICG/overscroll-scrollend-events

Thank you for the note, @smfr! The information related to snapping for the proposed snapped event might be mingled into the scrollend event, as both happen after the scrolling action has finished. Though I believe both events are distinct enough to be handled separately. This is especially true if we consider adding several events related to snapping.

The order in which they'd get fired is probably not that important as both are defined not to be cancelable and scrollend is currently defined as being async, but logically snapping causes the scroll action to end, so I'd say snapped before scrollend.

Sebastian

Schepp commented 4 years ago

I would like to also point to this request by me, aiming in a similar direction: https://webwewant.fyi/wants/65/

This is not just about events, but also about offering some sort of Scroll Snap API to programmatically scroll to certain snap points. As for the events, I proposed these two things which might be worth considering here:

  1. I'd like to have a snap event, once the element has snapped to a point, with info on which snap point of how many total snap points it just snapped to, so that I can update a progress indicator.

  2. I'd like to see the scroll event getting a new property which tells me if a scroll event was user-created or if it results from automatic scrolling (also interesting for the smooth scrolling coming from CSS scroll-behavior).

fvpDev commented 2 years ago

Hey y'all! As a young web dev I am super excited for the implementation of this. How's it coming along? Also, thank you for being awesome!

SebastianZ commented 1 year ago

@Schepp

This is not just about events, but also about offering some sort of Scroll Snap API to programmatically scroll to certain snap points.

I agree that there should be a way to explicitly scroll to certain snap points. Though I believe that should be discussed separately from the event model discussed here. So I created #8558 for it.

  1. I'd like to have a snap event, once the element has snapped to a point, with info on which snap point of how many total snap points it just snapped to, so that I can update a progress indicator.

Does this really require to know how many snap points there are? I think for a progress indicator it should be enough to know the target element. With that, you can easily calculate the progress.

  1. I'd like to see the scroll event getting a new property which tells me if a scroll event was user-created or if it results from automatic scrolling (also interesting for the smooth scrolling coming from CSS scroll-behavior).

Can you tell a concrete use case that requires a distinction between the two methods?

Sebastian