Check whether HTML element has scrollbars

JavascriptDomScrollbarOverflow

Javascript Problem Overview


What's the fastest way of checking whether an element has scroll bars?

One thing of course is checking whether element is larger than its viewport, which can easily be done by checking these two values:

el.scrollHeight > el.offsetHeight || el.scrollWidth > el.offsetWidth

but that doesn't mean that it has scrollbars as well (so it can actually be scrolled by humans).

Question

How do I check for scrollbars in a 1 cross browser and 2 javascript only (as in no jQuery) way?

Javascript only, because I need as small overhead as possible, because I'd like to write a very fast jQuery selector filter

// check for specific scrollbars
$(":scrollable(x/y/both)")

// check for ANY scrollbar
$(":scrollable")

I suppose I'd have to check for overflow style settings but how do I do that in a cross browser way?

Additional edit

Not only overflow style settings. Checking whether an element has a scrollbar isn't as trivial as it seems. The first formula I've written above works fine when element doesn't have a border, but when it does (especially when border is of considerable width), offset dimension can be larger than scroll dimension but the element can still be scrollable. We actually have to subtract borders from offset dimension to get the actual scrollable viewport of the element and compare that to scroll dimension.

For future reference

:scrollable jQuery selector filter is included in my .scrollintoview() jQuery plugin. Complete code can be found in my blog post if anybody needs it. Even though it didn't provide the actual solution Soumya's code considerably helped me solve the problem. It pointed me in the right direction.

Javascript Solutions


Solution 1 - Javascript

I found this somewhere a couple of weeks ago. It worked for me.

var div = document.getElementById('container_div_id');

var hasHorizontalScrollbar = div.scrollWidth > div.clientWidth;
var hasVerticalScrollbar = div.scrollHeight > div.clientHeight;

/* you'll get true/false */

Solution 2 - Javascript

Try:

For vertical scroll bar > el.scrollHeight > el.clientHeight

For horizontal scrollbar > el.scrollWidth > el.clientWidth

I know this works for IE8 and Firefox 3.6+ at least.

Solution 3 - Javascript

This may seem (or be) a little hackish, but you could test the scrollTop and scrollLeft properties.

If they're greater than 0, you know there are scrollbars. If they're 0, then set them to 1, and test them again to see if you get a result of 1. Then set them back to 0.

Example: http://jsfiddle.net/MxpR6/1/

function hasScroll(el, direction) {
    direction = (direction === 'vertical') ? 'scrollTop' : 'scrollLeft';
    var result = !! el[direction];

    if (!result) {
        el[direction] = 1;
        result = !!el[direction];
        el[direction] = 0;
    }
    return result;
}

alert('vertical? ' + hasScroll(document.body, 'vertical'));
alert('horizontal? ' + hasScroll(document.body, 'horizontal'));

I believe there's a different property for IE, so I'll update in a minute with that.

EDIT: Appears as though IE may support this property. (I can't test IE right now.)

http://msdn.microsoft.com/en-us/library/ms534618(VS.85).aspx

Solution 4 - Javascript

Here is yet another solution:

As a few people pointed out, simply comparing offsetHeight and scrollHeight is not enough since they differ on elements with overflow hidden, etc., that still don't have scrollbars. So here I'm also checking if overflow is scroll or auto on the computed styles for the element:

var isScrollable = function(node) {
  var overflowY = window.getComputedStyle(node)['overflow-y'];
  var overflowX = window.getComputedStyle(node)['overflow-x'];
  return {
    vertical: (overflowY === 'scroll' || overflowY === 'auto') && node.scrollHeight > node.clientHeight,
    horizontal: (overflowX === 'scroll' || overflowX === 'auto') && node.scrollWidth > node.clientWidth,
  };
}

Solution 5 - Javascript

I maybe a little late to the party, but...

I believe you can detect for scrollbars with e.offsetWidth vs. e.clientWidth. Offset width includes borders and scrollbars, padding and width. Client width includes padding and width. Please see:

https://developer.mozilla.org/en/DOM/element.offsetWidth (second image) https://developer.mozilla.org/en/DOM/element.clientWidth (second image)

You need to check:

  1. Whether or not the element has overflow set to auto/scroll (including overflowX/Y) using the computed/cascaded/current style.
  2. If the element does have overflow set to auto/scroll. Establish the offsetWidth and clientWidth.
  3. If the clientWidth is less than the offsetWidth - right border (found again through the computed/cascaded/current style), then you know you have a scrollbar.

Do the same for the vertical (offset/clientHeight).

IE7 reports a clientHeight of 0 for some elements (I haven't checked why), therefore you always need the first overflow check.

Hope this helps!

Solution 6 - Javascript

There are several problems in case of checking the existence of scrollbars one of which is that in mac you don't have any visible scrollbar so both all the solutions above wouldn't give you an accurate answer.

So because the browser's rendering isn't very frequent you can check the having scroll with changing scroll and then setting it back:

const hasScrollBar = (element) => {
  const {scrollTop} = element;

  if(scrollTop > 0) {
    return true;
  }

  element.scrollTop += 10;

  if(scrollTop === element.scrollTop) {
    return false;
  }

  // undoing the change
  element.scrollTop = scrollTop;
  return true;
};

Solution 7 - Javascript

For IE11 (Internet Explorer 11) I had to change the logic to:

// Subtract 3 (a small arbitrary number) to allow for IE reporting a difference of 1 when no scrollbar is present
var hasVerticalScrollbar = div.scrollHeight - 3 > div.clientHeight;

This is because IE reports scrollHeight as 1 larger than clientHeight when no scrollbar is present but approx 9 larger when a scrollbar is present

Solution 8 - Javascript

If you need to know if theres a scrollbar present for the whole webpage and with full browser support you can use this:

const hasScrollbar = document.body.scrollHeight > window.innerHeight

It's important to use window.innerHeight instead of document.body.clientHeight because in some mobile browsers clientHeight will not get the size of the address bar but scrollHeight will, so you get wrong calculations.

Solution 9 - Javascript

Just messing around here as none of the above solutions worked out for me (so far). I have found some success with comparing a Div's scrollheight against its offsetHeight

var oh = $('#wrapDiv').get(0).offsetHeight;
var sh = $('#wrapDiv').get(0).scrollHeight;

It seems to give me an acurate comparison...so far. Does someone know if this is legitimate?

Solution 10 - Javascript

Add an 100% wide element inside it. Then set overflow to hidden. If the element's computed style (from jQ) changes, the parent had a scrollbar.

EDIT: It seems you want a cross browser method like getComputedStyle. Try:

function getCSS(_elem, _style)
{
    var computedStyle;
    if (typeof _elem.currentStyle != 'undefined')
        computedStyle = _elem.currentStyle;
    else
        computedStyle = document.defaultView.getComputedStyle(_elem, null);
    return computedStyle[_style];
}

Solution 11 - Javascript

none of this answers are correct. you have to use this :

var div = document.getElementById('container_div_id');

var hasHorizontalScrollbar = (div.offsetWidth > div.clientWidth);
var hasVerticalScrollbar = (div.offsetHeight > div.clientHeight);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRobert KoritnikView Question on Stackoverflow
Solution 1 - JavascriptjzhingaView Answer on Stackoverflow
Solution 2 - JavascriptGaryView Answer on Stackoverflow
Solution 3 - Javascriptuser113716View Answer on Stackoverflow
Solution 4 - JavascriptlotifView Answer on Stackoverflow
Solution 5 - Javascriptuser140628View Answer on Stackoverflow
Solution 6 - JavascripthakobpoghView Answer on Stackoverflow
Solution 7 - Javascriptdanday74View Answer on Stackoverflow
Solution 8 - JavascriptSebastian HernandezView Answer on Stackoverflow
Solution 9 - JavascriptMichaelView Answer on Stackoverflow
Solution 10 - JavascriptSoumyaView Answer on Stackoverflow
Solution 11 - JavascripthamidView Answer on Stackoverflow