Skip to content

Instantly share code, notes, and snippets.

@dperini
Last active September 5, 2020 22:53
Show Gist options
  • Save dperini/ac3d921d6a08f10fd10e to your computer and use it in GitHub Desktop.
Save dperini/ac3d921d6a08f10fd10e to your computer and use it in GitHub Desktop.
/*
* How to detect which element is the scrolling element in charge of scrolling the viewport:
*
* - in Quirks mode the scrolling element is the "body"
* - in Standard mode the scrolling element is the "documentElement"
*
* webkit based browsers always use the "body" element, disrespectful of the specifications:
*
* http://dev.w3.org/csswg/cssom-view/#dom-element-scrolltop
*
* This feature detection helper allow cross-browser scroll operations on the viewport,
* it will guess which element to use in each browser both in Quirk and Standard modes.
* See how this can be used in a "smooth scroll to anchors references" example here:
*
* https://dl.dropboxusercontent.com/u/598365/scrollTo/scrollTo.html
*
* It is just a fix for possible differences between browsers versions (currently any Webkit).
* In case the Webkit bug get fixed someday, it will just work if they follow the specs. Win !
*
* Author: Diego Perini
* Updated: 2014/09/18
* License: MIT
*
*/
function getScrollingElement() {
var d = document;
return d.documentElement.scrollHeight > d.body.scrollHeight &&
d.compatMode.indexOf('CSS1') == 0 ?
d.documentElement :
d.body;
}
@matijs
Copy link

matijs commented Mar 11, 2015

Could you think of a situation in which this would result in Firefox (in standards mode) returning the "body" instead of the documentElement?
I have a situation where if I run the script immediately after the opening tag I get document.documentElement (as expected) whereas if I run the script later (just before some scrolling magic) it returns document.body.

@RByers
Copy link

RByers commented Mar 23, 2015

See discussion on this approach here: https://code.google.com/p/chromium/issues/detail?id=157855. There are various reported issues with it.

@RByers
Copy link

RByers commented Mar 24, 2015

Note that this does return body for unscrollable pages (if a page can't be scrolled at all then really neither element is appropriate, but probably either will do).

@dperini
Copy link
Author

dperini commented Apr 9, 2015

@RByers,
is there an expected scrolling behavior for unscrollable pages ?
Also see here: operasoftware/devopera#242

@mathiasbynens
Copy link

This code is now being used (with Diego’s permission) in a document.scrollingElement polyfill: https://github.com/mathiasbynens/document.scrollingElement

@RByers
Copy link

RByers commented Apr 24, 2015

Actually, I don't understand this logic at all. In most cases in Chrome and Firefox, document.body.scrollHeight == document.documentElement.scrollHeight and so you'll get 'body' even when that's not correct. Other than wacky cases where both html and body have 'overflow' set, I believe these values always both include the document scroll height. They can be different when the body has additional margin/padding but that still doesn't give you any signal about which element is the scroller and so shouldn't be impacting the return value.

Is there a case I'm missing? Can you give me an example where this actually returns 'documentElement'?

@RByers
Copy link

RByers commented Apr 24, 2015

Oh, I think I see. This relies on body having some margin. In that case I think it does work. I was testing on a few pages that happened to have 'body {margin: 0};' (not an uncommon pattern) where it falls down.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment