Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
* 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:
* 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:
* 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 :

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 commented Mar 23, 2015

See discussion on this approach here: There are various reported issues with it.

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 commented Apr 9, 2015

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

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

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 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