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
[cssom-view][proposal] beforescroll event #4172
Comments
I'm not sure this is something people would want given having such an event will necessarily disable all accelerated scrolling (at least if the page uses non-passive listeners for that). |
@emilio just so we're on the same page - by accelerated scrolling you mean how Chrome for example increases If yes, then there might have been a misunderstanding. My idea was to be able to interrupt scrolling right before the UA changes |
No, with accelerated scrolling I mean scrolling without going back to the main thread (async scrolling, etc). Right now when you use your trackpad, or when you use the wheel and there are no Your event would mean that the UA cannot really scroll without dispatching an event and then knowing if that event is default-prevented. |
From my understanding, this:
Needs to be changed so that it checks if there are You could also flag the |
If there's a slow script running on the page, right now you can scroll. If the browser needs to wait for that script to finish in order to trigger the event (and run more script) in order to figure out if it can even start scrolling, it defeats the point of accelerated scrolling. |
Making them passive would indeed work, but that prevents you from being able to |
From what I understand, having a non-passive Well, can't it be the same for the If I have a passive I think the |
Sure, it can be a passive-by-default event or what not, and behave like you describe, I'm just unsure if people are going to be keen to add a potential performance footgun like that. |
I think that people would very much prefer sacrificing this performance benefit over using hacks, workarounds, overflow, and whatnot to "prevent" the browser from scrolling or using Accelerated scrolling is a performance benefit after all. If you use |
My first issue here. I'll be making a suggestion for CSSOM View Module Events.
Problem
We have solid control over various input events. For keyboard, we have
keydown
,keyup
,keypress
(deprecated). For mouse, we haveclick
,dblclick
,mouseup
,mousedown
... We don't have great control over scroll, though.The
scroll
event is useful for implementing functionality that responds to scrolling, but is too limited for more advanced use cases. It's emitted after the actual scrolling has taken place and therefore doesn't provide much control. You can'tpreventDefault()
and prevent scrolling and if you usedocument.scrollingElement.scrollTop
for scroll-based animations, for example, they can be glitchy since they would lag one frame.Touch events and the
wheel
event might be used as an alternative. They fire before scrolling has taken place, but they don't fire continuously. They can only be used to know when scrolling is expected to start, which is not very helpful.Solution
A middle ground between the
scroll
andwheel
events is what's needed. My suggestion is to have thebeforescroll
event which:deltaY
/deltaX
properties, similar towheel
defaultPrevented
which prevents scrollThe delta properties specify with how much pixels the element will be scrolled in the current event loop. Or, in other words,
element.scrollTop + event.deltaY
in thebeforescroll
event should be equal toelement.scrollTop
in thescroll
event. This is useful because:scroll
mentioned abovescrollTop
between thescroll
event emissions (which also lag one frame)You can call
preventDefault()
to prevent scrolling, but not any followingbeforescroll
events. In Chrome, this code:...would log similar to the following after a single
wheel
event withdeltaY
of100
:Here's a fiddle. With
beforescroll
, you should be able to do this:...and the scroll target should not be scrolled, while the logs should read:
Since the actual scroll was prevented,
scroll
events should not fire after thebeforescroll
handler.Why
Having this event would allow developers to implement advanced behaviors based on scrolling accurately. It would also give a reliable way to prevent scrolling, which is currently not easily achievable. You could prevent scrolling with the mouse wheel by calling
preventDefault()
on thewheel
event, but you can still scroll with the scrollbar, arrow keys,scrollTo()
or even clicking a link with a hash.Use cases:
beforescroll
to prevent vertical scrolling and use the delta properties to scroll that section horizontally. When the section is fully scrolled, vertical scroll is no longer prevented and the user can continue scrolling the site. This is a UX pattern for carousel-like content.beforescroll
could allow for better hijacking which, in the right hands, can improve UX. For example, while the site visitor scrolls through a section, the developer could usebeforescroll
to prevent scrolling, optionally animate something inside the section withdeltaY
, and usedocument.scrollingElement.scrollTop += Math.ceil(event.deltaY / 2)
. This would still scroll the page vertially, with the UA's expected scroll easing, only at half the speed. This way, the developer can easily implement dynamic visuals for a content section and then emphasize them by directing the user's attention with slower scrolling.beforescroll
to implement scroll-triggered animations via the delta properties. This would be easier and more accurate compared to manually measuring delta with ascroll
handler.Edit: This event would also open possibilities for carousel libraries on mobile. They could use
overflow:auto
and control the behavior withbeforescroll
, instead of settingoverflow:hidden
and manually scrolling the target by monitoring touch events.The text was updated successfully, but these errors were encountered: