w3c/css-houdini-drafts

[scroll-customization-api] is there still interest/ongoing discussions for scroll customization?

andyearnshaw opened this issue · 5 comments

I've recently been working on a new component that does some interesting effects with scrolling. One of the effects is speeding up/slowing down the scrolling at certain points, essentially absorbing or multiplying some of the scroll delta to produce this effect. Since scrolling is done off the main thread and I want to support touch/fling, I'm using a hidden scrollbar that captures the scroll delta before applying my modifications and passing that on to the actual scrollable element. Naturally, this means actual scrolling is lagging behind by about a frame, but it's not really noticeable.

It looks like the explainer for scroll customization is about 8 years old and I can't find any other discussions about it. I presume the API would be more similar to a worklet these days. Having posted suggestions for virtualised scrolling APIs on the webcomponents and css-wg trackers in the past, as well as the recent work I've been doing, I can't help but feel this part of the explainer is still very relevant:

The fundamental problem here is that scrolling on the web is a big "magical" black-box. In other UI frameworks scrolling is usually implemented as a library (with extensibility points) on top of primitives. The goal of the Houdini Scroll Customization proposal is to break open this black box to make scrolling on the web extensible.

Just some of the stuff I'm doing with scrolling at the moment:

  • Scroll speed "warping"
  • Virtualised scrolling (arbitrary scrollWidth/scrollHeight, decoupled from layout)
  • Synchronised scrolling
  • Transforms based on scroll position

Having a dedicated API for scroll customisation would really simplify all of these things and help remedy the quirks that occur due to the black-box nature of scrolling.

/cc @RByers

Thanks for reaching out Andy! From Chrome team's perspective I think we largely decided that this was just incredibly difficult to do, even for us, AND unlikely to get support across engines. Lately we've been focusing instead on higher-level APIs like scroll animations. I still agree with what I said about higher-level APIs being fundamentally limited and low-level primitives being more powerful. But I also now think it was a grave error for me to argue against prioritizing such APIs like snap points in favour of getting scroll customization primitives (I just underestimated the challenge by at least an order of magnitude). While I still agree with much of the philosophy of the extensible web manifesto, I think we got the priority wrong then. IMHO in a world of quite limited resources for browser engine investment (especially considering across WebKit/Gecko/Chromium) the first priority should be to ensure the 95% use cases can be done easily and (crucially) in a highly-performant way with declarative APIs. Making the remaining 5% possible in some way is also important probably less so.

Do you know to what extent the things you've been looking at could work on top of declarative APIs like scroll animations? Perhaps some are possible with relatively minor addition to those designs? Transforms based on scroll positions, synchronized scrolling and scroll speed "warping" all sound to me like things that should either be possible to do already or that require only minor additions.

I don't see any path in the next few years by which the Chrome team will be able to invest seriously in the low-level scroll customization primitives I proposed here. At the same time, if someone else was willing to make the (IMHO massive) investment in Chromium to do so in a sustainable and quality way, I don't think we'd necessarily be opposed to it. Just given the limited resources (believe it or not) we have to invest in this space, I think we can get more value for web developers via the higher-level approaches. WDYT?

I really appreciate the candid response, Rick. I completely understand the point of view, it's important to put the needs of the many before the few. That being said, for me, scroll customisation is a recurring, frustrating problem that I don't think can be solved by high-level APIs.

I regularly work on tables and lists that are completely custom views on customer data. They can, potentially, have millions of rows and/or columns. 95% of customers probably have less than a thousand rows and less than 30 columns. In reality for me, I can't ignore the 5% because they are paying the most! So, I (and others, including the Microsoft Excel team) run into issues like maximum scrolling sizes, which browser vendors tell me they cannot resolve:

Maximum element size is too restrictive for virtual scrolling (crbug)
Maximum element size is too restrictive for virtual scrolling (Bugzilla)

I also never really got any traction proposing a standards-based solution. It's a problem that can be worked around with a poorer user experience or highly complex custom scrolling implementations, but the low-level nature of the problem impacts use of any high-level APIs, especially CSS-based ones. Solving this problem at the standards level would go a long way towards reducing a lot of hacky code in a couple of components.

With regards to scroll speed "warping", I need to directly manipulate the delta by which a user has scrolled and increase it or decrease it accordingly. The scrollbar would actually move slower at this point. It's a very specific use case and I don't see it being applicable in many situations, we're talking more like the 0.001% which is why I'd be excited by the prospect of a low-level API.

That being said, what I'm working on right now is like a custom layout based on scroll position as well as scroll delta. It's very complex, and I need for the implementation to be easy to understand and low risk of edge cases. Using high-level APIs and workarounds amps up the complexity and makes it feel like a bunch of messy hacks to achieve a flawed solution, to the point where you trading one poor user experience for another. Ultimately, any solution I come up with ties scrolling back to the main thread and means I have to work really hard to keep rendering performance the main priority, which is why something like a worklet would be ideal.

Again, I really appreciate the way you responded. I understand that these problems are not a priority for the Chrome team, it's likely true of other browser vendors also. Given that it's been 5 years since I originally tried to do something about the maximum element/scroll sizes, and 8 years since your draft proposal for scroll customisation, I may have to accept the fact that it's never going to happen!

Thanks for describing your use case and pointers to bugs. I agree it's a problem that we haven't solved this use case via any mechanism. Apps like Google Sheets just take over completely from the browser, drawing to canvas and doing their own scrolling. I agree this is a shame - it forces the entire main thread to live under realtime constraints of <16ms, which can be very hard (or, on some devices, practically impossible) in practice. I'm sorry that we've effectively been giving you the run-around by trying to solve it in different ways over the years which have, I think, all failed.

I do think we should be looking for pragmatic ways to make such virtual/infinite scrollers work well. @flackr and @chrishtr for their latest thoughts.

I regularly work on tables and lists that are completely custom views on customer data. They can, potentially, have millions of rows and/or columns. 95% of customers probably have less than a thousand rows and less than 30 columns. In reality for me, I can't ignore the 5% because they are paying the most! So, I (w3c/csswg-drafts#3397 (comment), including the Microsoft Excel team) run into issues like maximum scrolling sizes

While a bit of a hack, for use cases like this you could use a large scroller with a scroll listener and if the scrolled distance is a small amount (e.g. page-down or less) you would track the relative change and update the scroll position to be the absolute position. And if the scroll is a large amount (e.g. scrollbar drag / home / end keys) use the overall absolute position as the position to seek to. Here's the example from the crbug updated to use this strategy (Note, the math needs to be adjusted slightly to ensure that you have sufficient scroll range to get to the end of the scroll - which is why right now you can get to 0, 0 but not the last row):

https://jsfiddle.net/flackr/gw132dev/

Ideally a browser primitive would let the developer provide the DOM around the current scroll position and the browser could even scroll that content quickly without needing it to be drawn frame by frame by the developer, and only when you scroll far we would need the developer to provide the new content. We could also use similar strategies to my demo to allow for larger ranges than are normally scrollable. I'll have to think more about what exactly this would look like.

@flackr thanks for your suggestion! I'm actually using a different hack in the latest version: two scrollbars via nested containers, the inner scrollbar is hidden and always resets to middle. That means you can still drag the visible outer scrollbar around for reduced accuracy scrolling, then the hidden scrollbar absorbs mouse/touch/keyboard scrolling in a similar manner to your suggestion here. It's a custom element, so I've redefined the scrollWidth and scrollHeight properties to be writable and support large values. It works reasonable well, but it is still a hack.

Thank you both for considering what browsers could do to help with our use case!