Meeting notes: Non-<body> root scrollers

18 views
Skip to first unread message

Rick Byers

unread,
Nov 19, 2015, 2:16:49 PM11/19/15
to David Bokan, Dima Voytenko, input-dev, David Morell, Malte Ubl, Alexandre Elias
Context: Dima (G+ / AMP teams) has previously convinced us that we need to make it easier to build full screen scrolling web apps.

tl;dr: David now has a prototype build which sets the root scroller via setting the document.scrollingElement property.  Dima says its awesome (modulo a few bugs), when can we ship it?  David will create a GitHub repo and start working on an explainer.

Detailed notes:
  • Recap on key benefits:
    • provide isolation of scroll state between views without loosing "root scroller" features like top controls hiding
    • explicit indication of the primary scroller can simplify some scenarios, eg. accessibility
  • Prototype build here
    • Simple demo here and tweaked version of Dima's mini-app here
    • Still has some issues with position:fixed and position:relative
  • Agreed we really need an explicit API for this
  • Are there restrictions on what you can set it to?
    • In current prototype it just must have a box
    • But for now probably simplest to define the API to work only for elements which fill the screen - that would be adequate.
  • What about the issue of modal dialogs?
    • These want to prevent scrolling from hitting the document
    • Should we prioritize the CSS 'scroll-chaining' property?  No.
    • Dima says this isn't a huge deal today, you can hack around it.  In chrome using overflow:hidden, in Safari need an uglier hack
    • Setting the root scroller will eliminate this problem - just use a non-scrollable document
  • Attribute setter or explicit method
    • Probably a method - easier to feature detect and clearer failure path
    • Maybe similar to Element.requestFullscreen()?
  • Should the root scroller change the value of document.scrollingElement
    • probably?
    • would then also affect window.scrollX/Y properties and window.scrollTo method
  • What should be behavior be if the element is removed from the DOM?
  • Should scrolling that hits the extent of the element chain up still?
    • No, don't want it to
    • Except that it does "chain" to the top controls
  • Any accessibility implications?
    • Should hopefully make accessibility simpler (can tell the tools what the primary scroller is)
  • When could we likely ship this?
    • Hard part is precise spec'ing and getting consensus with the other browser vendors, but if the value is high we can push harder
    • Real usage experience from web developers can really help cut through the debate.
    • Should we reach out to facebook to see if it'd help them too?  Yes, definitely  - once we have explainer written.
    • Rick's best guess - somewhere around 6 months.  Will be David's primary focus.
  • Could possibly expose sooner via the experimental framework
  • Next steps:
    • David to create a GitHub repo and write a short "explainer", then iterate with Dima and David
    • Once we're happy with the explainer, send an intent-to-implement and work on landing patches behind a flag
    • In parallel start sketching out a detailed spec
    • Aiming to have it landed with status=experimental by early Q1 sometime
    • Then we'll start active engagement with other developers and browser vendors

Chris Harrelson

unread,
Nov 19, 2015, 5:00:27 PM11/19/15
to Rick Byers, David Bokan, Dima Voytenko, input-dev, David Morell, Malte Ubl, Alexandre Elias
I think shipping root-layer-scrolling (the feature skobes@ and szager@ were working on until recently) will get almost all of the benefits, right? (except for omnibox hiding?)

Chris

Steve Kobes

unread,
Nov 19, 2015, 6:17:50 PM11/19/15
to Chris Harrelson, Rick Byers, David Bokan, Dima Voytenko, input-dev, David Morell, Malte Ubl, Alexandre Elias
Root layer scrolling (which we are still working on) doesn't expose any new web-facing functionality, but it might make this easier to implement.

David Bokan

unread,
Nov 19, 2015, 6:29:39 PM11/19/15
to Steve Kobes, Chris Harrelson, Rick Byers, Dima Voytenko, input-dev, David Morell, Malte Ubl, Alexandre Elias
Right, I think implementation might be a bit simpler, but hiding the omnibox is kind of the whole point (and overscroll glow, and pull-to-refresh, and accessibility tools, and any other functionality we eventually tack on to scrolling the viewport). This feature is essentially telling the browser "make this *element* the root scroller (i.e. the layout viewport)" and all the consequences that come with it.

The details and semantics are still mostly undecided, but it might mean that window.scrollTo/innerWidth/etc would apply to the designated element rather than the documentElement. Perhaps we may even want to use the element to affix position:fixed elements. For now, the main benefit we're looking to provide is to let an author write an app with a natural concept of "views" that can be swapped in and out without losing all the browser UX.

Dima Voytenko

unread,
Nov 19, 2015, 7:09:56 PM11/19/15
to David Bokan, Steve Kobes, Chris Harrelson, Rick Byers, input-dev, David Morell, Malte Ubl, Alexandre Elias
That's right.

Alexandre Elias

unread,
Nov 19, 2015, 7:28:37 PM11/19/15
to Dima Voytenko, David Bokan, Steve Kobes, Chris Harrelson, Rick Byers, input-dev, David Morell, Malte Ubl
One thought: the fullscreen API spec defined a new painting concept of "top layer": https://fullscreen.spec.whatwg.org/#new-stacking-layer .  Would that be appropriate to reuse here, or if not why?

(That's one subquestion of the more general question of how does the root scroller interact with/hide with the rest of the DOM.)

David Bokan

unread,
Nov 20, 2015, 1:53:57 PM11/20/15
to Alexandre Elias, Dima Voytenko, Steve Kobes, Chris Harrelson, Rick Byers, input-dev, David Morell, Malte Ubl
If I understand correctly, the top layer concept is there to affect paint order and how elements are displayed in general. Our proposal here doesn't affect painting of the content at all. The author would have to write their app to make sure the scrollingElement is visible. We're mainly concerned with how the designated element interacts with the Browser UI and user events.

To the more general question of how this interacts with the rest of the DOM, we haven't really thought about the details and edge cases yet. One proposal was that we could limit scrollingElement only to boxes that fill the viewport. This isn't strictly necessary though. You could imagine having a slightly smaller root scroller with some DOM behind it as background. Or implementing a scrolling popup by making it the scrollingElement, thus giving it overscroll glow and disabling scrolling on the background content.

An important area we'll have to think through is how to handle events and their capture/bubbling behavior. My first thoughts are that the scrollingElement should be a bubbling/capture boundary but I don't know about use cases or potential issues with that yet. It'll be much easier to find these problem areas once we've built a more robust prototype and let people experiment with it.

Alexandre Elias

unread,
Nov 20, 2015, 4:03:26 PM11/20/15
to David Bokan, Dima Voytenko, Steve Kobes, Chris Harrelson, Rick Byers, input-dev, David Morell, Malte Ubl
One basic question I have is do we conceive of the API call as promoting the scrollable div itself, or promoting its contents while retaining the existing root Viewport?  The answer isn't entirely obvious, and we need to nail that down as it seems connected to most of the other problems.

On Fri, Nov 20, 2015 at 10:53 AM, David Bokan <bo...@google.com> wrote:
If I understand correctly, the top layer concept is there to affect paint order and how elements are displayed in general. Our proposal here doesn't affect painting of the content at all. The author would have to write their app to make sure the scrollingElement is visible. We're mainly concerned with how the designated element interacts with the Browser UI and user events.

In that case, what happens to the rest of the contents?  Do we consider the scroll offset for the the rest of the content to be permanently locked to (0, 0), and anything absolutely positioned near the top of the document with a high z-index would behave like top-aligned position: fixed? Or does it retain its own scrollable Viewport with a distinct scroll offset allowing those to be scrolled off?  If the former, what happens when the scrollable div is unpromoted?  If the latter, are you planning to generalize CC to support multiple Viewports?


To the more general question of how this interacts with the rest of the DOM, we haven't really thought about the details and edge cases yet. One proposal was that we could limit scrollingElement only to boxes that fill the viewport.

The enterFullscreen API already relayouts the element it was called on to fit the fullscreen viewport, so it's something we need to support in general.  The proposal to restrict to boxes that already fill the viewport sounds like it would have bad ergonomics (what's the failure mode if it didn't fill the viewport?) without simplifying our implementation much.

I don't think you can totally assume a fixed size because of top controls complexities anyway.  During top controls moves, a naive implementation that e.g. locked the viewport size to maximum viewport size might have glitches particularly with the vertical scrollbar, which would overflow off the bottom of the screen (a subtle but important problem that vertical_adjust solves in CC today).
 
This isn't strictly necessary though. You could imagine having a slightly smaller root scroller with some DOM behind it as background. Or implementing a scrolling popup by making it the scrollingElement, thus giving it overscroll glow and disabling scrolling on the background content.

An important area we'll have to think through is how to handle events and their capture/bubbling behavior. My first thoughts are that the scrollingElement should be a bubbling/capture boundary but I don't know about use cases or potential issues with that yet. It'll be much easier to find these problem areas once we've built a more robust prototype and let people experiment with it.

Fullscreen API had the same problem.  We've had various bugs in it involving scrolling gestures bubbling up to the document and causing overscroll glow, or pinch and double-tap gestures resizing the fullscreen video controls.  I worked around those with the big hammer of disabling scroll and pinch entirely, but that's awkward.

Dima Voytenko

unread,
Nov 20, 2015, 5:05:37 PM11/20/15
to Alexandre Elias, David Bokan, Steve Kobes, Chris Harrelson, Rick Byers, input-dev, David Morell, Malte Ubl
I don't think we necessarily need to redirect window.scrollTo, pageX/Y, etc to the scrolling element. If it becomes natural - sure. If not, it's not necessary. Whoever prefers to work with scrollable divs already employ the appropriate APIs and given them option to do the same on window is not very important.

I also think it'd make a lot of sense to restrict the scrolling box to be laid out full screen (e.g. top=0,left=0,right=0,bottom:0). In practice it's always easy to achieve and this is a good restriction in general.

David Bokan

unread,
Nov 20, 2015, 5:23:01 PM11/20/15
to Alexandre Elias, Dima Voytenko, Steve Kobes, Chris Harrelson, Rick Byers, input-dev, David Morell, Malte Ubl
On Fri, Nov 20, 2015 at 4:03 PM, Alexandre Elias <ael...@chromium.org> wrote:
One basic question I have is do we conceive of the API call as promoting the scrollable div itself, or promoting its contents while retaining the existing root Viewport?  The answer isn't entirely obvious, and we need to nail that down as it seems connected to most of the other problems.

On Fri, Nov 20, 2015 at 10:53 AM, David Bokan <bo...@google.com> wrote:
If I understand correctly, the top layer concept is there to affect paint order and how elements are displayed in general. Our proposal here doesn't affect painting of the content at all. The author would have to write their app to make sure the scrollingElement is visible. We're mainly concerned with how the designated element interacts with the Browser UI and user events.

In that case, what happens to the rest of the contents?  Do we consider the scroll offset for the the rest of the content to be permanently locked to (0, 0), and anything absolutely positioned near the top of the document with a high z-index would behave like top-aligned position: fixed? Or does it retain its own scrollable Viewport with a distinct scroll offset allowing those to be scrolled off?  If the former, what happens when the scrollable div is unpromoted?  If the latter, are you planning to generalize CC to support multiple Viewports?

I'm leaning towards the former, though there's no need to lock its scroll offset to (0, 0). Basically, anything in view would behave like position: fixed. When the div is unpromoted, the document becomes the scrollingElement again and so it becomes scrollable again. The way I have this implemented in the prototype Rick linked is that I've generalized the compositing code to support moving the visual viewport around in the layer tree and designating an element to be the outer viewport. The document still has the clip and scrolling layers so it could in theory be scrolled as well. Here's a picture of the layer tree (some boilerplate layers omitted):

Root Transform Layer
   |---Inner Container
         |---Page Scale Layer
               |---Inner Scroll Layer    (*Inner Scroll Layer)
                     |---Outer Clip Layer
                           |---Outer Scroll Layer  (*Outer Scroll Layer)
                                 |---#document Content
                                       |---DIV Clip Layer
                                             |---DIV Content Layer


Gets transformed into:

Root Transform Layer
   |---Outer Clip Layer
         |---Outer Scroll Layer
               |---#document Content
                     |---Inner Container
                           |---Page Scale Layer
                                 |---Inner Scroll Layer    (*Inner Scroll Layer)
                                       |---DIV Clip Layer
                                             |---DIV Content Layer  (*Outer Scroll Layer)

Where the (*Inner/Outer Scroll Layer) denotes that layer as being the inner/outer_viewport_scroll_layer in CC/LayerTreeHost

Our scroll bubbling logic means that when a scroll reaches the inner container layer, the scroll is passed to cc::Viewport which, after scrolling itself, consumes the remainder in the form of overscroll. This has the effect of stopping bubbling. 
 


To the more general question of how this interacts with the rest of the DOM, we haven't really thought about the details and edge cases yet. One proposal was that we could limit scrollingElement only to boxes that fill the viewport.

The enterFullscreen API already relayouts the element it was called on to fit the fullscreen viewport, so it's something we need to support in general.  The proposal to restrict to boxes that already fill the viewport sounds like it would have bad ergonomics (what's the failure mode if it didn't fill the viewport?) without simplifying our implementation much.

I don't think you can totally assume a fixed size because of top controls complexities anyway.  During top controls moves, a naive implementation that e.g. locked the viewport size to maximum viewport size might have glitches particularly with the vertical scrollbar, which would overflow off the bottom of the screen (a subtle but important problem that vertical_adjust solves in CC today).

We can restrict or make the box have width/height: 100% so that we're not using a fixed size. Note that since we actually make the div the outer viewport, CC performs the vertical_adjustment on it as it does on the document today. We could also use the fullscreen mechanism to fill the viewport as you mention. While it's not necessary to fill the viewport, it's our main use case and does simplify things somewhat. It's also easier to ease a restriction later on if we realize it's useful than to tighten it so I think we should start with that.
 
 
This isn't strictly necessary though. You could imagine having a slightly smaller root scroller with some DOM behind it as background. Or implementing a scrolling popup by making it the scrollingElement, thus giving it overscroll glow and disabling scrolling on the background content.

An important area we'll have to think through is how to handle events and their capture/bubbling behavior. My first thoughts are that the scrollingElement should be a bubbling/capture boundary but I don't know about use cases or potential issues with that yet. It'll be much easier to find these problem areas once we've built a more robust prototype and let people experiment with it.

Fullscreen API had the same problem.  We've had various bugs in it involving scrolling gestures bubbling up to the document and causing overscroll glow, or pinch and double-tap gestures resizing the fullscreen video controls.  I worked around those with the big hammer of disabling scroll and pinch entirely, but that's awkward.

Right. The nice thing about this is that all the events stop or are cleared out at the viewport so the bubbling works out very naturally. I didn't have to change anything in CC to get this behavior.

Malte Ubl

unread,
Jan 4, 2016, 5:23:04 PM1/4/16
to David Bokan, Alexandre Elias, Dima Voytenko, Steve Kobes, Chris Harrelson, Rick Byers, input-dev, David Morell
Hey All,

I just wanted to bring this thread back on the agenda and was wondering whether this is on anyone's OKRs? Basically in AMP we have no work around, since documents are in iframes we cannot do any of the hacks we typically do to scroll away the header.

Happy new year!

Malte

Rick Byers

unread,
Jan 4, 2016, 9:35:44 PM1/4/16
to Malte Ubl, David Bokan, Alexandre Elias, Dima Voytenko, Steve Kobes, Chris Harrelson, input-dev, David Morell
Yep this is still bokan@'s top priority, but we haven't done much of the hard work of engaging with other vendors yet.  We're writing Q1 OKRs now and so will have a concrete plan by next week sometime.

Rick

David Bokan

unread,
Jan 26, 2016, 1:40:43 PM1/26/16
to Rick Byers, Malte Ubl, Alexandre Elias, Dima Voytenko, Steve Kobes, Chris Harrelson, input-dev, David Morell
Hi Malte and others,

Sorry! I forgot to follow up on this until now. As Rick mentioned, this is part of our Q1 OKRs and my top priority this quarter. It's taking longer than I predicted at the end of last quarter since we've decided to implement this in a different way under the hood (using the on-going scroll customization work - though not in such a way that we'd be blocked on that).

My expectation for the end of this quarter is to have at least started conversations with the other vendors about this and have them convinced that the problem is worth solving. In the mean time, I'd like to have an experimental implementation ready to go behind a flag in M51 (I'll try for M50 but that might be a bit aggressive). That should serve as a starting point for design debate and evangelism.

Let me know if you have any questions or comments.

Thanks,
David

Dima Voytenko

unread,
Apr 13, 2016, 2:13:39 PM4/13/16
to David Bokan, Rick Byers, Malte Ubl, Alexandre Elias, Steve Kobes, Chris Harrelson, input-dev, David Morell
Hi All!

How are you all? Just wanted to check in on the subject.

Do we have a bug to track? If not, could you please create one? It's fine if it's currently restricted to Google only.

-d

David Bokan

unread,
Apr 13, 2016, 3:19:20 PM4/13/16
to Dima Voytenko, Rick Byers, Malte Ubl, Alexandre Elias, Steve Kobes, Chris Harrelson, input-dev, David Morell
Hi Dima,

The bug to follow is crbug.com/505516. Going has been slower than I initially expected (lots of refactoring on the Blink side) but I've got most of that done (crbug.com/591124) and the major patch to enable this on the main thread is lgtm'd and about to be landed (https://codereview.chromium.org/1840113005/). I expect to have the main thread version working within about a week or two, my next patch should enable that. I'd like to have main and CC versions implemented behind a flag in the current milestone (M52).

I'll be sure to ping you once I have something behind a flag you can experiment with.

Thanks,
David

Dima Voytenko

unread,
Apr 13, 2016, 3:22:45 PM4/13/16
to David Bokan, Rick Byers, Malte Ubl, Alexandre Elias, Steve Kobes, Chris Harrelson, input-dev, David Morell
Thanks David! This sounds great. Will track progress through bug now.
Reply all
Reply to author
Forward
0 new messages