w3c / csswg-drafts

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

[css-overscroll-scrollend-events] Content has no way of understanding whether it is being overscrolled or whether scroll has ended #3801

Open NavidZ opened 5 years ago

NavidZ commented 5 years ago

When users scroll in an embedded iframes the events don't get bubbled outside of the embedded iframes to the embedder. However, if the embedded iframe has no scroller or has some scroller that has reached its extent the scroll might get chained to the embedder content and causes scroll there.

In this case the embedder content will get no input events (such as touch events that caused the scroll) but it keeps getting the scroll events. However, as oppose to the inner iframe which can get the touchend events to specify user is done interacting with the page, the embedder content has no way of determining whether the scroll has finished or whether maybe the content is being overscrolled.

We wanted to propose a new event type to support the behavior explained above. We started an incubation over here.

I wanted to move this under WICG but let me know if you prefer somewhere else.

smfr commented 4 years ago

I envisioned overscroll events being about rubber banding within a given scrollable area (sending scroll event with negative offsets is not very web-compatible). Using them to propagate information about scrolls between iframe needs more thought, particularly across origin boundaries.

NavidZ commented 4 years ago

I envisioned overscroll events being about rubber banding within a given scrollable area (sending scroll event with negative offsets is not very web-compatible)

This is the intention. The sign only tries to capture the direction of it. i.e. if you are overscrolling/rubbber banding from the right or from the left. Note that these are not scroll events. So they do not interfere with the current web. So I don't think they would cause any web compat issues. The proposal is to have a new event for rubber banding called overscroll that has this delta that could be negative.

Using them to propagate information about scrolls between iframe needs more thought, particularly across origin boundaries

The scrolling itself is already exposed somewhat. As you may start the finger within a cross origin iframe and the outerframe might get scrolled (due to scroll chaining). This is just to expose the information in the same space (i.e. scrolling) to the content that is being scrolled. So it is not so much as leaking information (like touch move path or anything) to a cross origin. What do you think?

smaug---- commented 4 years ago

Hmm, so overscroll would be dispatched where in this iframe case? Say top level page can be scrolled but iframe has been scrolled to top already and one tries to scroll up iframe. Now user ends up scrolling the page to top. Both iframe and top level page has been tried to be scrolled, but in practice only top level page has been scrolled. Which document gets overscroll? Both?

NavidZ commented 4 years ago

Hmm, so overscroll would be dispatched where in this iframe case? Say top level page can be scrolled but iframe has been scrolled to top already and one tries to scroll up iframe. Now user ends up scrolling the page to top. Both iframe and top level page has been tried to be scrolled, but in practice only top level page has been scrolled. Which document gets overscroll? Both?

The element that is found as the scrolling element in scroll chain will scroll and hence that same element should get the overscroll and scrollend event. In your example since the iframe is not scrollable in that direction anymore browser skips it and finds the first node in the scroll chain that is scrollable and scrolls that node. This scroll chaining logic is already specced in https://drafts.csswg.org/css-overscroll/#scroll-chaining

Note that the iframe will never get scrolled and will never get any scroll events either. So it doesn't make sense to get overscroll or scrollend events either. It will not have the overscroll effects either as it was not the scrolling element.

NavidZ commented 4 years ago

@smfr @smaug---- @SamFort-MSFT are we good on this?

SamFort-MSFT commented 4 years ago

Does scrollend fire after all overscroll events are done firing for a scroller? Or at the moment when events transition from scroll to overscroll? It's not clear to me right now because I'm not certain what a 'scroll sequence' as referenced here means. Or something else?

smfr commented 4 years ago

Yes I think it could be clearer. What I would expect, for sequence of user scrolls and a rubber band, would be

scroll scroll ... scroll overscroll ... overscroll scrollend

I think overscroll events need a scroll offset (maybe different from deltaX/deltaY) which is the overscroll distance. scrolled should have properties for the final scroll position.

InstyleVII commented 4 years ago

Overall this looks good to me. My only question isn't technical but around who the customers are for this and if any web developers have specifically been asking for this or a way to solve this problem. Do you have any data around that (Twitter polls or comments or issues filed)?

NavidZ commented 4 years ago

what @smfr described in terms of the sequence is what we intended. Note that I already sent a PL for CSSOM View to spec this in place instead of the WICG spec @SamFort-MSFT referenced (i.e. this one). In terms of the wording to make sure we capture this behavior feel free to checkout that pull request instead as that is very much inline with the scroll events dispatching as well.

I think overscroll events need a scroll offset (maybe different from deltaX/deltaY) which is the overscroll distance.

While overscrolling the scroll offset is always at the extent of the scrollers (i.e. 0 or max offset) in the direction of scrolling and can always be reached with getting the scrollLeft/Top from the scrollers.

scrollend should have properties for the final scroll position. I don't mind this at all. But you should note that scroll event doesn't have that either. I believe scrollend and scroll kind of fall into the same bucket. Having said that I don't mind at all adding the offset to both of them but these can be accessed by scrollLeft/Top of the scroller at any time.

Overall this looks good to me. My only question isn't technical but around who the customers are for this and if any web developers have specifically been asking for this or a way to solve this problem. Do you have any data around that (Twitter polls or comments or issues filed)?

Regarding the current issues there is already a developer commenting in the original discourse thread. We also have some internal customer which hit this problem when the pages have ads (which might be cross origin and hence the outer page gets scrolled without knowing when the scroll actually finished or overscrolled.

SamFort-MSFT commented 4 years ago

I'm wondering how the overscroll event works with inertial scroll, specifically the calculation of the deltaX/Y values. When the overscroll is caused by the user keeping their finger(s) down and 'pulling' on the screen or touchpad, there is a definitive delta that the user attempted to move which can be reported. With a UA's default affordance for overscroll, this delta may be modified using some sort of simulated tension so that the actual overscroll delta is a subset of the user delta. But, the deltaX/Y appears to report the actual user delta (without any tension) if I'm reading the CSSOM View spec proposed changes correctly. When inertia is involved, there is no user movement value to report as far as I know. What would one report for deltaX/Y in this case? Should the UA compute a user delta that would have been moved to generate the actual overscroll delta used from the inertia animation? That seems to make sense - but depending on the UA 'tension' algorithm used, it might not be trivial.

Also, if the user overscrolls while keeping the finger down, and then flings out of the overscroll in the opposite direction, I believe we can get this sequence of events:

scroll scroll overscroll (based on actual user movement) overscroll (based on computed user deltas due to inertia?) scroll scroll scrollend

Or if the fling travels all the way to the other scroll extent, one could even see:

scroll scroll overscroll (based on actual user movement) overscroll (based on computed user deltas due to inertia?) scroll scroll overscroll (based on computed user deltas due to inertia?) overscroll (based on computed user deltas from tension returning to the normal scroll boundary) scrollend

Do these align with your expectations?

NavidZ commented 4 years ago

They do. Generally speaking scrollend is not matched with touchend. It is matched with the end of the scroll. So if there are continuation of the scroll due to fling and whatnot scrollend is delayed accordingly.

Also, if the user overscrolls while keeping the finger down, and then flings out of the overscroll in the opposite direction, I believe we can get this sequence of events:

scroll scroll overscroll (based on actual user movement) overscroll (based on computed user deltas due to inertia?) scroll scroll scrollend

Currently, in Chromium implementation when you do overscroll as soon as you change direction you start scrolling (i.e. changing scroll offset). So it is as if overscroll delta goes to 0 directly. With this mode, as soon as you change direction you should be expecting scroll events and not overscroll as the page is scrolling indeed. However, I can imagine we can have another overscroll-behavior css value to indicate the overscroll should ease back instead of immediately starting scroll in the opposite direction for example. In that mode then the series of events should become the same as your first example. This additional control seems to be the perfect fit for additional values in overscroll-behavior.

Or if the fling travels all the way to the other scroll extent, one could even see:

scroll scroll overscroll (based on actual user movement) overscroll (based on computed user deltas due to inertia?) scroll scroll overscroll (based on computed user deltas due to inertia?) overscroll (based on computed user deltas from tension returning to the normal scroll boundary) scrollend

The same goes for the second example. Chromium doesn't do overscroll on fling at this point. So it actually stops scrollings and sends scrollend as soon as it hits the boundary. I can imagine again have an attribute in overscroll-behavior to let the user agent do that behavior. If that was allowed then your second output expectation would also be correct.

SamFort-MSFT commented 4 years ago

Thoughts on my questions about deltaX/Y values when they are being updated via inertia or the tension/spring like effect to move an overscroll back to its normal scroll boundary?

smfr commented 4 years ago

I think the problem there is that different platforms will have different kinds of inputs that trigger overscroll, so the only thing you can accurately report is the overscroll pixel offset (if any). I don't know what data would be useful on Android where you show the blue halo thing.

NavidZ commented 4 years ago

I agree with what @smfr says. Basically my initial thought when I was proposing this was that we would report the same number of pixels we would have scrolled if we hadn't hit the boundary with the current state. I'm certainly open to introduce other attributes to let the page control what curve and formula should browser use for these kind of effects if there is a requirement for them.

SamFort-MSFT commented 4 years ago

If I'm understanding correctly, @smfr is saying to report the actual overscroll amount but @NavidZ is saying to report the amount we would have scrolled if we didn't hit a scroll boundary. Due to the tension/spring like effect or glow effect those are not the same thing. It's also not clear to me that we can compute the amount we would have scrolled if we didn't hit a scroll boundary when playing animations to return from an overscrolled state to the normal scroll boundary. Right now it's unclear to me what deltaX/Y would actually report.

NavidZ commented 4 years ago

What I have put in the spec proposal is what I mentioned above. I believe this is less confusing vs considering what spring like effect a browser uses. In the plain form assuming you have your finger on the screen the deltas will be the amount of pixels the finger has moved. Let me know what you think. I'm open to suggestions if you think the default behavior is better if we incorporate the spring effect of each browser into these deltas.

Regarding, actually calculating this, at least in Chromium, it is other way around as far I as know. We always have an (accumulated) real deltas (e.g. such as finger movements) and then we translate that to overglow effect you see that spring behavior on. So we don't lose that original accumulated value.

NavidZ commented 4 years ago

Since the last time I fixed a bug in Chromium after some discussion with @SamFort-MSFT as Chromium was not doing any sort of accumulation and it was only reporting the delta from the last frame. We believe that wasn't as useful as the total amount of delta that we overscrolled so far and it is now inline with how the pull request spec it.

I was wondering if there is any other concerns or comments around this feature? @smfr, does this feature address other possible use cases you had in mind? I want to make sure we have all related use cases we have in mind at this point covered at least.

smaug---- commented 4 years ago

Is https://github.com/w3c/csswg-drafts/pull/4537 up-to-date to what has been discussed here?

bxff commented 2 years ago

Any updates on this?

dontcallmedom commented 4 months ago

I believe this issue was addressed by https://github.com/w3c/csswg-drafts/commit/a8955e554a916aefbff4896f3b0ceab005d0f81b