Is it possible to check the overflow:auto
of a div?
For example:
HTML
(scrollWidth/Height - clientWidth/Height) is a good indicator for the presence of a scrollbar, but it will give you a "false positive" answer on many occasions. if you need to be accurate i would suggest using the following function. instead of trying to guess if the element is scrollable - you can scroll it...
function isScrollable( el ){
var y1 = el.scrollTop;
el.scrollTop += 1;
var y2 = el.scrollTop;
el.scrollTop -= 1;
var y3 = el.scrollTop;
el.scrollTop = y1;
var x1 = el.scrollLeft;
el.scrollLeft += 1;
var x2 = el.scrollLeft;
el.scrollLeft -= 1;
var x3 = el.scrollLeft;
el.scrollLeft = x1;
return {
horizontallyScrollable: x1 !== x2 || x2 !== x3,
verticallyScrollable: y1 !== y2 || y2 !== y3
}
}
function check( id ){
alert( JSON.stringify( isScrollable( document.getElementById( id ))));
}
#outer1, #outer2, #outer3 {
background-color: pink;
overflow: auto;
float: left;
}
#inner {
width: 150px;
height: 150px;
}
button { margin: 2em 0 0 1em; }
<div id="outer1" style="width: 100px; height: 100px;">
<div id="inner">
<button onclick="check('outer1')">check if<br>scrollable</button>
</div>
</div>
<div id="outer2" style="width: 200px; height: 100px;">
<div id="inner">
<button onclick="check('outer2')">check if<br>scrollable</button>
</div>
</div>
<div id="outer3" style="width: 100px; height: 180px;">
<div id="inner">
<button onclick="check('outer3')">check if<br>scrollable</button>
</div>
</div>
You need element.scrollHeight. Compare it with $(element).height()
.
Ugh everyone's answers on here are incomplete, and lets stop using jquery in SO answers already please. Check jquery's documentation if you want info on jquery.
Here's a generalized pure-javascript function for testing whether or not an element has scrollbars in a complete way:
// dimension - Either 'y' or 'x'
// computedStyles - (Optional) Pass in the domNodes computed styles if you already have it (since I hear its somewhat expensive)
function hasScrollBars(domNode, dimension, computedStyles) {
dimension = dimension.toUpperCase()
if(dimension === 'Y') {
var length = 'Height'
} else {
var length = 'Width'
}
var scrollLength = 'scroll'+length
var clientLength = 'client'+length
var overflowDimension = 'overflow'+dimension
var hasVScroll = domNode[scrollLength] > domNode[clientLength]
// Check the overflow and overflowY properties for "auto" and "visible" values
var cStyle = computedStyles || getComputedStyle(domNode)
return hasVScroll && (cStyle[overflowDimension] == "visible"
|| cStyle[overflowDimension] == "auto"
)
|| cStyle[overflowDimension] == "scroll"
}
I made a new custom :pseudo selector for jQuery to test whether an item has one of the following css properties:
I wanted to find the closest scrollable parent of another element so I also wrote another little jQuery plugin to find the closest parent with overflow.
This solution probably doesn't perform the best, but it does appear to work. I used it in conjunction with the $.scrollTo plugin. Sometimes I need to know whether an element is inside another scrollable container. In that case I want to scroll the parent scrollable element vs the window.
I probably should have wrapped this up in a single plugin and added the psuedo selector as a part of the plugin, as well as exposing a 'closest' method to find the closest (parent) scrollable container.
Anywho....here it is.
$.isScrollable jQuery plugin:
$.fn.isScrollable = function(){
var elem = $(this);
return (
elem.css('overflow') == 'scroll'
|| elem.css('overflow') == 'auto'
|| elem.css('overflow-x') == 'scroll'
|| elem.css('overflow-x') == 'auto'
|| elem.css('overflow-y') == 'scroll'
|| elem.css('overflow-y') == 'auto'
);
};
$(':scrollable') jQuery pseudo selector:
$.expr[":"].scrollable = function(a) {
var elem = $(a);
return elem.isScrollable();
};
$.scrollableparent() jQuery plugin:
$.fn.scrollableparent = function(){
return $(this).closest(':scrollable') || $(window); //default to $('html') instead?
};
Implementation is pretty simple
//does a specific element have overflow scroll?
var somedivIsScrollable = $(this).isScrollable();
//use :scrollable psuedo selector to find a collection of child scrollable elements
var scrollableChildren = $(this).find(':scrollable');
//use $.scrollableparent to find closest scrollable container
var scrollableparent = $(this).scrollableparent();
UPDATE: I found that Robert Koritnik already came up with a much more powerful :scrollable pseudo selector that will identify the scrollable axes and height of scrollable containers, as a part of his $.scrollintoview() jQuery plugin. scrollintoview plugin
Here is his fancy pseudo selector (props):
$.extend($.expr[":"], {
scrollable: function (element, index, meta, stack) {
var direction = converter[typeof (meta[3]) === "string" && meta[3].toLowerCase()] || converter.both;
var styles = (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(element, null) : element.currentStyle);
var overflow = {
x: scrollValue[styles.overflowX.toLowerCase()] || false,
y: scrollValue[styles.overflowY.toLowerCase()] || false,
isRoot: rootrx.test(element.nodeName)
};
// check if completely unscrollable (exclude HTML element because it's special)
if (!overflow.x && !overflow.y && !overflow.isRoot)
{
return false;
}
var size = {
height: {
scroll: element.scrollHeight,
client: element.clientHeight
},
width: {
scroll: element.scrollWidth,
client: element.clientWidth
},
// check overflow.x/y because iPad (and possibly other tablets) don't dislay scrollbars
scrollableX: function () {
return (overflow.x || overflow.isRoot) && this.width.scroll > this.width.client;
},
scrollableY: function () {
return (overflow.y || overflow.isRoot) && this.height.scroll > this.height.client;
}
};
return direction.y && size.scrollableY() || direction.x && size.scrollableX();
}
});
A No Framework JavaScript Approach, checks for both vertical and horizontal
/*
* hasScrollBars
*
* Checks to see if an element has scrollbars
*
* @returns {object}
*/
Element.prototype.hasScrollBars = function() {
return {"vertical": this.scrollHeight > this.style.height, "horizontal": this.scrollWidth > this.style.width};
}
Use it like this
if(document.getElementsByTagName("body")[0].hasScrollBars().vertical){
alert("vertical");
}
if(document.getElementsByTagName("body")[0].hasScrollBars().horizontal){
alert("horizontal");
}
Maybe a more simple solution.
if ($(document).height() > $(window).height()) {
// scrollbar
}