document.body.scrollTop vs. document.documentElement.scrollTop

1,436 views
Skip to first unread message

Mike Sherov

unread,
Aug 30, 2014, 10:33:49 PM8/30/14
to blink-dev
Hello blink devs,

About a year ago, I advocated for a change in Blink to stop reporting +0 values for body.scrollTop (unless the body itself was not overflow:visible), and simultaneously start reporting +0 values for document.documentElement.scrollTop instead. I advocated the same change for setters as well. 

This change brought Blink in line with FF and IE and the actual HTML5 spec.

Unfortunately, this broke several "designed for Blink/ WebKit" only sites, including several built in chrome pages. 

The change was partially reverted so that both body and documentElement returned >0. This fixed the blink only sites but broke a few sites that we're working around the original browser discrepancy by doing "body.scrollTop + documentElement.scrollTop".

The change was then hidden behind an experimental flag and a use counter was implemented to attempt to gauge this behavior. The canonical "solution" became "documentElement.scrollTop || body.scrollTop".

However, this leaves Blink with a fundamentally flawed behavior that is only enabled experimentally with a use counter that really can't detect improper usage.

Since that time, the chrome internal pages I believe have fixed themselves, and any work to move this forward further has stalled.

I'd love to get to a place where Blink can simply implement the spec, which will put it in line with FF and IE, and not force developers to hack the solution in, while leaving libraries like jQuery with no way to actually determine what the state of the page is.

The current behavior (without experimental flags on) leaves libraries with no way to detect if a body is scrolled independently of a window. The experimental behavior suffers the same fate with the added badness of thinking the window AND body is scrolled regardless if only the window OR body is scrolled.

How can we determine when and if to move forward to the spec compliant behavior?

See the following bugs for some history:


Thanks for your time and attention!

Sent from Mailbox

Antonio Gomes

unread,
Aug 31, 2014, 2:14:38 AM8/31/14
to Mike Sherov, blink-dev
Hi

On Sat, Aug 30, 2014 at 10:33 PM, Mike Sherov <mike....@gmail.com> wrote:
 
The change was partially reverted so that both body and documentElement returned >0. This fixed the blink only sites but broke a few sites that we're working around the original browser discrepancy by doing "body.scrollTop + documentElement.scrollTop".

The change was then hidden behind an experimental flag and a use counter was implemented to attempt to gauge this behavior. The canonical "solution" became "documentElement.scrollTop || body.scrollTop".
However, this leaves Blink with a fundamentally flawed behavior that is only enabled experimentally with a use counter that really can't detect improper usage.


Just to clarify, what Blink implements as of now behind a runtime flag is the spec-compliant behavior for scrollTop/Left, not the variant implementation where both documentElement.scrollTop and body.scrollTop returned values > 0.

Since that time, the chrome internal pages I believe have fixed themselves, and any work to move this forward further has stalled.

I'd love to get to a place where Blink can simply implement the spec, which will put it in line with FF and IE, and not force developers to hack the solution in, while leaving libraries like jQuery with no way to actually determine what the state of the page is.

Please list what FF and IE do differently than Blink with regards to scrollTop/Left (when the runtime toggle is on) and I can gladly help with that. For instance, blink also properly implements scrollTop/Left for <body> itself is scrollable, and so is <html>.

The current behavior (without experimental flags on) leaves libraries with no way to detect if a body is scrolled independently of a window. The experimental behavior suffers the same fate with the added badness of thinking the window AND body is scrolled regardless if only the window OR body is scrolled.

Not sure I followed. Could you provide a snippet where Blink fails with the runtime flag  ON?

PhistucK

unread,
Aug 31, 2014, 2:23:51 AM8/31/14
to Antonio Gomes, Mike Sherov, blink-dev
Without having any such flag enabled, the current behavior (in Chrome 37) for me, in quirks and in standards mode, is that document.body.scrollTop is non zero when I scroll and document.documentElement.scrollTop is zero.

Unless I am missing something, what was exactly changed? I believe it has always been this (incorrect) way.


PhistucK


To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

Antonio Gomes

unread,
Aug 31, 2014, 2:37:14 AM8/31/14
to PhistucK, Mike Sherov, blink-dev
Right. In default configurations, Blink behaviors the same in quirks and standard modes with regards to {documenElemtent,body}.scrollTop/Left : documentElement.scrollTop/Left is always 0, body.scrollTop/Left is always return the actual scroll position.

The runtime flag triggers the spec-compliant, firefox/IE-like behavior:

- quirks mode: body.scrollTop/Left reflect the actual page scroll position, unless the <body> itself is scrollable independently from the <html> tag. documentElement.scrollTop/Left is always 0.

- non-quirks mode: documentElement.scrollTop/Left reflect the actual page scroll position. body.scrollTop/Left is always 0, unless the <body> tag itself is scrollable, independently from the <html> tag.

For completeness, the flag is chrome://flags/#enable-experimental-web-platform-features
--
--Antonio Gomes

PhistucK

unread,
Aug 31, 2014, 3:17:50 AM8/31/14
to Antonio Gomes, Mike Sherov, blink-dev
So just to verify that I get it - eventually, the (enabled by default) behavior never changed - right?
(I am verifying, because there were a lot of e-mails and updates regarding changing this behavior to be more compliant and I thought something was eventually landed and not reverted, some interim - on by default - solution, but you seem to note that nothing actually changed in this regard)


PhistucK

Antonio Gomes

unread,
Aug 31, 2014, 3:23:18 AM8/31/14
to PhistucK, Mike Sherov, blink-dev
It changed, then it was half reverted, then was fully reverted in favor of a fixed behind a runtime flags.

So the enabled by default behavior continues to be the long standing broken one.
--
--Antonio Gomes

PhistucK

unread,
Aug 31, 2014, 3:36:35 AM8/31/14
to Antonio Gomes, Mike Sherov, blink-dev
So it never actually changed. Thank you for the answer.


PhistucK

Mike Sherov

unread,
Aug 31, 2014, 6:59:20 AM8/31/14
to PhistucK, Antonio Gomes, blink-dev
I believe Antonio's last answer to be correct. It seems I missed a step in the history. My apologies. 

I have a few questions more, thanks for the patience!

Antonio, what is Blink's current behavior re: setters for these properties, both the default and behind the flag?

If the flagged version is the correct behavior for both getters and setters, what are the current blockers to it becoming the default behavior?

Thanks again!

Sent from Mailbox

Antonio Gomes

unread,
Sep 2, 2014, 4:21:00 PM9/2/14
to blin...@chromium.org, phis...@gmail.com, toni...@gmail.com
Setters and Getters behaviors are symmetric with the runtime flag on and off.

Such flip will likely break sites that do browser detection instead of feature detection. It includes some google site [2]. One major one is facebook, that you listed originally in your email [1].

Whee facebook is fixed, I believe it might be worth to try to make it ON by default, in canaries and see what breaks. Would be nice to have DevRel team on board to reach out to sites that could eventually need changes.

[1] https://code.google.com/p/chromium/issues/detail?id=342307
[2] https://code.google.com/p/chromium/issues/detail?id=398933

Rick Byers

unread,
Sep 26, 2014, 1:50:25 PM9/26/14
to Antonio Gomes, blink-dev, PhistucK Productions, rsc...@chromium.org, Eric Seidel
I agree that bringing Chrome's behavior in-line with the spec (and IE, Firefox) is valuable here.  We (chrome input team) are trying to make scrolling more rational (easier to reason about and customize) and this is a clear wart in our scrolling behavior today.

I agree with the plan to ensure high profile sites are fixed, and then to try enabling the flag again (shipping it even if there are some minor sites still effected).  So it seems the actions from the bugs are:

I've re-opened the original bug to track enabling this behavior by default, and blocked it on the above bugs.

Rick

Rick Byers

unread,
Feb 9, 2015, 1:03:10 AM2/9/15
to Antonio Gomes, blink-dev, Simon Pieters, PhistucK Productions, Ryan Schoen, Eric Seidel, Elliott Sprehn, j...@whiteroomsoftware.com, Matt Rakow, aero...@chromium.org
To briefly re-cap this old thread: blink/WebKit have a bug where document scrolling is controlled via document.body instead of document.documentElement as per spec.  Our spec compliant behavior is behind the "ScrollTopLeftInterop" RuntimeEnabledFeature, and users still regularly complain about sites (like Facebook) being broken when this flag is enabled.

I want to try to make some progress on this issue - it's a big wart for web compat.  Eg. now that IE is using a WebKit user-agent in EdgeHTML do we really want to see them copy this wart in order to be compatible?

Google+ appears to now be fixed, but Facebook still has the bug.  Before we push again to reach out to Facebook, is there already an article somewhere that we can point developers at for the best cross-platform way to handle scrollTop/scrollLeft?  The getter is trivial (use || or +) but the setter is less so.  Do we just want to encourage folks to use window.scrollY instead of document.documentElement.scrollTop?  Or do you need to set the scrollTop on documentElement first, test if that got applied, and if not set it on body?

I want a simple library / code snippet for our dev-rel folks to be able to blast out before we seriously consider trying to ship this again.  But I DO think it's worth some web-compat pain to get this cleaned up.

Once we have a good best-practice to point at, and have done appropriate dev-rel including asking Facebook to correct their behavior, then I want to try shipping the spec compliant behavior to stable again.  

Rick

Rick Byers

unread,
Aug 20, 2015, 3:21:35 PM8/20/15
to Antonio Gomes, blink-dev, Simon Pieters, PhistucK Productions, Ryan Schoen, Eric Seidel, Elliott Sprehn, Jon Chester, Matt Rakow, aero...@chromium.org, Steve Kobes, input-dev
Another update with some good news and some bad news.

Thanks to document.scrollingElement and some great outreach, I've been able to get the few known major sites / libraries with issues to update not to depend on the blink/WebKit scrollTop bug.

As such, I've promoted scrollTopLeftInterop mode to  'experimental' again in Chrome 46.  We'll continue to watch carefully for feedback.  If you hear complaints of scroll-related behavior regressing in Chrome 46, you can ask people to try disabling the --enable-experimental-web-platform-features flag (and file a bug with "scrollTopLeftInterop" in it).  From previous experience, users often forget that they have enabled this, and it leads to confusion with being unable to reproduce bugs.

Unfortunately I've just uncovered an issue with a 'smooth scrolling' library used on a number of websites (157 of top 300k) which causes scrolling to break completely when scrollTopLeftInterop is enabled :-(.  The latest version of the library has this bug fixed, but the old version has been copied around for years and exists in a number of wordpress templates (among other places).  This library is generally only ever used on Chrome to compensate for our ongoing lack of a smooth scrolling feature (which all other browsers have), which is why their WebKit-specific code had previously gone unnoticed.

Our plan is to focus on shipping a great built-in smooth scroll feature, and then advocate for sites to stop using smoothscroll.js (it can be bad for scroll performance anyway).  Then (assuming no new major issues, and regardless of any change in usage of smoothscroll.js) I believe we should proceed with attempting to promote scrollTopLeftInterop to stable.  This is similar to the situation we found ourselves in with touch-action and hammer.js.  In that case, doing a good job of evangelism (eg. a google search for "scrolling broken Chrome Android 46" would point to simple guidance to update the broken library) resulted in a pretty swift (and, as far as we could see, not overly painful) update of affected sites.  Regardless, before we get to this point I'll do an "intent to ship" so we can debate the tradeoffs further.

The key thing is at this stage I believe it's better to postpone shipping so that we can give the guidance of "remove smoothscroll.js" once, instead of having to suggest "update your smoothscroll.js" and later "remove smoothscroll.js".

Feedback?

Thanks,
   Rick

PhistucK

unread,
Aug 20, 2015, 3:44:13 PM8/20/15
to Rick Byers, Antonio Gomes, blink-dev, Simon Pieters, Ryan Schoen, Eric Seidel, Elliott Sprehn, Jon Chester, Matt Rakow, aero...@chromium.org, Steve Kobes, input-dev
The truth is that I am not optimistic. I still think we should ship it, because it is important and this bug should just go away as soon as possible (from Safari as well, what are their plans?).
The case you mentioned (touch-action) is different, because it is a rather new API and developers that live on the edge are more receptive to breaking changes than others, while the old WordPress templates will probably not be changed, as well as websites that are working for years with the bug.

Good luck, anyway. :( I hope this story has a nice and short ending.


PhistucK

Rick Byers

unread,
Aug 20, 2015, 4:20:43 PM8/20/15
to PhistucK, Antonio Gomes, blink-dev, Simon Pieters, Ryan Schoen, Eric Seidel, Elliott Sprehn, Jon Chester, Matt Rakow, aero...@chromium.org, Steve Kobes, input-dev
On Thu, Aug 20, 2015 at 3:43 PM, PhistucK <phis...@gmail.com> wrote:
The truth is that I am not optimistic. I still think we should ship it, because it is important and this bug should just go away as soon as possible (from Safari as well, what are their plans?).

They've expressed a desire to change once it appears sufficiently compatible to do so - which hopefully means shortly after we do (we'll see!).
 
The case you mentioned (touch-action) is different, because it is a rather new API and developers that live on the edge are more receptive to breaking changes than others, while the old WordPress templates will probably not be changed, as well as websites that are working for years with the bug.

Yes, there's definitely risk here that we'll break some sites that don't get fixed.  But that's the case with every change we make.  Personally I see our responsibilities as (in order):
 1) keep any disruption of the user experience to a minimum (i.e. the vast majority of users should never notice a problem - this is our rough 0.03% rule)
 2) make it as easy as possible for motivated developers to identify and adapt to the change
 3) move towards a platform that best meets the needs of users and developers in the future (simple, interoperable, easy to predict, etc.)

So as long as we're not violating #1 (usage is very low), and we've done our due diligence for #2 (published good guidance, given some warning, etc.), then #3 kicks in and we should make the breaking change :-) 

PhistucK

unread,
Aug 20, 2015, 5:52:17 PM8/20/15
to Rick Byers, Antonio Gomes, blink-dev, Simon Pieters, Ryan Schoen, Eric Seidel, Elliott Sprehn, Jon Chester, Matt Rakow, aero...@chromium.org, Steve Kobes, input-dev
Well, is this change not violating #1? You cannot even tell, because you cannot even add a use counter for it. Only a manual inspection detects this, pretty much. Is less than 0.03% of the web not vulnerable to the scrollTop issue? This is such a common issue (from my experience, though I tried my best to always use both of the ways simultaneously in my projects) that I am very skeptical it does not violate the 0.03% rule. Top sites are one part, but there are countless other websites on the web.

Once this is in, I hope this sticks and never look back!


PhistucK

Philip Jägenstedt

unread,
Aug 21, 2015, 5:05:49 AM8/21/15
to PhistucK, Rick Byers, Antonio Gomes, blink-dev, Simon Pieters, Ryan Schoen, Eric Seidel, Elliott Sprehn, Jon Chester, Matt Rakow, aero...@chromium.org, Steve Kobes, input-dev
Use counters aren't the only way to guess what the impact for users might be. Searching the httparchive is another, and when that fails running an experiment on the dev channel or similar is also a possibility.

FWIW, Rick's plan sounds good to me, that only 157 of the top 300k sites are affected makes it at least plausible that the problem can be fixed.
Reply all
Reply to author
Forward
0 new messages