Instantly share code, notes, and snippets.

Embed
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:
*
* 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

This comment has been minimized.

Show comment
Hide comment
@matijs

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

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

This comment has been minimized.

Show comment
Hide comment
@RByers

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

This comment has been minimized.

Show comment
Hide comment
@RByers

RByers 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).

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

This comment has been minimized.

Show comment
Hide comment
@dperini

dperini Apr 9, 2015

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

Owner

dperini commented Apr 9, 2015

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

@mathiasbynens

This comment has been minimized.

Show comment
Hide comment
@mathiasbynens

mathiasbynens Apr 9, 2015

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

mathiasbynens commented Apr 9, 2015

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

@RByers

This comment has been minimized.

Show comment
Hide comment
@RByers

RByers 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

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

This comment has been minimized.

Show comment
Hide comment
@RByers

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

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