I recently contributed a fix to the bootstrap framework that detects on-screen scrollbars to determine whether or not the body should be padded when a modal window is opened to prevent shifting of background contents. Detecting on-screen scrollbars turned out to be a bit more involved than I initially anticipated. The tl;dr, semi-näive version: This works for most browsers. Basically it checks to see if the width of the This solution behaves correctly when IE10+ has This certainly seems to function as expected for IE9+; however, IE8 is our newest anchor browser so IE8 should be addressed in any ostensibly “cross-browser” approaches. One thing to check is the Again, this is an oversimplification. The The two values of the This is, once again, a bit of a simplification. In quirksmode in IE8 The final solution looks like this: If I missed something, or if this solution is a bit of an oversimplification (le sigh), please let me know in the comments.window
element (read: including scrollbars) is greater than the width of the root element of the page (read: without scrollbars). If the width of the page with scrollbars is greater than the width of a page without scrollbars it would stand to reason that the extra width is a scrollbar.@-ms-viewport { width: device-width; }
set (as it is in the bootstrap framework), which seems to result in scrollbars being auto-hidden. This solution also works for Chrome on the Mac where the scrollbars are automagically hidden.window.innerWidth
doesn’t exist on IE8. Any workarounds you see utilizing document.documentElement
will not include scrollbars in the reported width, so document.docutmentElement
will not be an adequate substitute in < IE9.scrollHeight
. If the scrollHeight
of the root element is greater than the clientHeight
of the root element, then that root element is going to need to scroll to show the overflowing content:var hasScrollbar
if (typeof window.innerWidth === 'number')
hasScrollbar = window.innerWidth > document.documentElement.clientWidth
hasScrollbar = hasScrollbar ||
document.documentElement.scrollHeight > document.documentElement.clientHeight
overflow
property of the root element can modify the appearance of scrollbars (to create on-screen faux llbars). Of course, once again, IE and modern browsers differ about how they’ve implemented the javascript api for accessing element styles. We can account for this difference and grab the overflow property like this:var overflowStyle
if (typeof document.documentElement.currentStyle !== 'undefined')
overflowStyle = document.documentElement.currentStyle.overflow
overflowStyle = overflowStyle || window.getComputedStyle(document.documentElement, '').overflow
overflow
or overflow-y
properties that will create scrollbars are visible
and auto
provided that the scrollHeight
is greater than the clientHeight
. A value of scroll
for the overflow
or overflow-y
properties will always cause a scrollbar.document.documentElement.clientHeight
is 0. The root element is document.body
. This won’t affect most people reading this, but just to be on the safe side let’s add it into our solution.var hasScrollbar = function() {
// The Modern solution
if (typeof window.innerWidth === 'number')
return window.innerWidth > document.documentElement.clientWidth
// rootElem for quirksmode
var rootElem = document.documentElement || document.body
// Check overflow style property on body for fauxscrollbars
var overflowStyle
if (typeof rootElem.currentStyle !== 'undefined')
overflowStyle = rootElem.currentStyle.overflow
overflowStyle = overflowStyle || window.getComputedStyle(rootElem, '').overflow
// Also need to check the Y axis overflow
var overflowYStyle
if (typeof rootElem.currentStyle !== 'undefined')
overflowYStyle = rootElem.currentStyle.overflowY
overflowYStyle = overflowYStyle || window.getComputedStyle(rootElem, '').overflowY
var contentOverflows = rootElem.scrollHeight > rootElem.clientHeight
var overflowShown = /^(visible|auto)$/.test(overflowStyle) || /^(visible|auto)$/.test(overflowYStyle)
var alwaysShowScroll = overflowStyle === 'scroll' || overflowYStyle === 'scroll'
return (contentOverflows && overflowShown) || (alwaysShowScroll)
}
Posted