Problem
Scroll chaining is the process of propagating the scroll delta to the the nearest scrollable parent element once an scrollable reaches its limit. Scroll chaining is not always desirable. For example consider a fixed/absolute position scroller whose scroll should not chain to parent scroller i.e., the document. You can find this UX pattern used in most chat boxes that live at the bottom of the page such as in Facebook or Gmail UI. (See this chrome bug for example)
To give you a sense of how popular preventing scroll chaining may be, according to my quick http-archive search -ms-scroll-chaining: none
is used in 0.4% of top 300K pages despite being limited in functionality and only supported on IE/Edge.
Current Solution
-ms-scroll-chaining is a vendor specific API which I believe is only supported by IE and Edge at the moment. The CSS property provides a simple declarative way to prevent propagation of scroll gestures to parent containers but unfortunately it is only limited to touch/touchpad scrolls. [1]
This means that currently the best cross-browser compatible way to prevent scroll propagation is to have a combination of blocking wheel event listener (bad for performance), blocking keyboard listeners for all scroll inducing keys, carefully crafted touch-action values, and perhaps even -ms-scroll-chaining. These are rather ugly and complex hacks that “-ms-scroll-chaining” should have been able to replace but it cannot in its current form.
Proposal
I think scroll-chaining
is not really useful until it can be used to prevent scroll propagation in the general case. Enabling that will make it much more useful to web developers and thus more compelling for UAs to implement. So I propose the following changes to its semantic:
-
scroll-chaining
should apply to all user scrolls including mouse, touch, keyboard, and others. Programmatic scroll APIs such asElement::scrollIntoView
are not affected by this. -
Scroll chaining be controlled independently for each axis. For example a component which does not overflow on horizontally should not prevent propagation on that axis if it only needs to prevent the vertical propagation. I suggest using
scroll-chaining-{x,y}
long-hands to match the overflow property.
Bonus Change
Specify what scroll-chaining means if it is added to the viewport defining element. Many browsers do navigation actions once user overscrolls the viewport. Lack of control over this behaviour has been a well-known pain for developers. We are experimenting with a new API to address this usecase but I think there is an opportunity here to leverage scroll-chaining
here and avoid a slightly different API. For example, if chaining is disabled on viewport then it should disable navigation actions.
Note that (1) and (bonus change) may pose some compat risk however I feel these would be limited. We can try to better understand these risks once there is some consensus that these are useful changes.
Side Notes
I am not sure why scroll-chaining: none
specifies a “bounce effect”. To me this looks like a user-agent specific affordance that does not need to be in the spec.
According to my tests the current definition is also bit out-dated compared to the current implementation in latest IE/Edge implementation. In particular, the property is not limited only to take effect during a manipulation but it also takes effect at the start of the manipulation. I think this is the right behavior anyways.
[1]
This property only applies to touch and touchpad input. Regardless of –ms-scroll-chaining value, for keyboard input the scroll does not chain, and for mouse input the scroll will always chain up to the nearest scrollable ancestor element.
[2]
Value that indicates the behavior that occurs when a user hits the scroll limit. chained : Initial value. The nearest scrollable parent element begins scrolling when the user hits a scroll limit during a manipulation. No bounce effect is shown. none: A bounce effect is shown when the user hits a scroll limit during a manipulation.