Check whether HTML element has scrollbars

Check whether HTML element has scrollbars

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.

Solutions/Answers:

Solution 1:

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:

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:

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:

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:

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:

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?