Is there any way that I can check if an element is visible in pure JS (no jQuery) ?
So, for example, in this page: Performance Bikes, if you hover over Deals (on the
If element is regular visible (display:block and visibillity:visible), but some parent container is hidden, then we can use clientWidth and clientHeight for check that.
function isVisible (ele) {
return ele.clientWidth !== 0 &&
ele.clientHeight !== 0 &&
ele.style.opacity !== 0 &&
ele.style.visibility !== 'hidden';
}
Plunker (click here)
So what I found is the most feasible method:
function visible(elm) {
if(!elm.offsetHeight && !elm.offsetWidth) { return false; }
if(getComputedStyle(elm).visibility === 'hidden') { return false; }
return true;
}
This is build on these facts:
display: none
element (even a nested one) doesn't have a width nor height.visiblity
is hidden
even for nested elements.So no need for testing offsetParent
or looping up in the DOM tree to test which parent has visibility: hidden
. This should work even in IE 9.
You could argue if opacity: 0
and collapsed elements (has a width but no height - or visa versa) is not really visible either. But then again they are not per say hidden.
According to this MDN documentation, an element's offsetParent
property will return null
whenever it, or any of its parents, is hidden via the display style property. Just make sure that the element isn't fixed. A script to check this, if you have no position: fixed;
elements on your page, might look like:
// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
return (el.offsetParent === null)
}
On the other hand, if you do have position fixed elements that might get caught in this search, you will sadly (and slowly) have to use window.getComputedStyle(). The function in that case might be:
// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
var style = window.getComputedStyle(el);
return (style.display === 'none')
}
Option #2 is probably a little more straightforward since it accounts for more edge cases, but I bet its a good deal slower, too, so if you have to repeat this operation many times, best to probably avoid it.
I've got a more performant solution compared to AlexZ's getComputedStyle() solution when one has position 'fixed' elements, if one is willing to ignore some edge cases (check comments):
function isVisible(el) {
/* offsetParent would be null if display 'none' is set.
However Chrome, IE and MS Edge returns offsetParent as null for elements
with CSS position 'fixed'. So check whether the dimensions are zero.
This check would be inaccurate if position is 'fixed' AND dimensions were
intentionally set to zero. But..it is good enough for most cases.*/
if (!el.offsetParent && el.offsetWidth === 0 && el.offsetHeight === 0) {
return false;
}
return true;
}
Side note: Strictly speaking, "visibility" needs to be defined first. In my case, I am considering an element visible as long as I can run all DOM methods/properties on it without problems (even if opacity is 0 or CSS visibility property is 'hidden' etc).
Improving on @Guy Messika's answer above, breaking and returning false if the center point' X is < 0 is wrong as the element right side may go into the view. here's a fix:
private isVisible(elem) {
const style = getComputedStyle(elem);
if (style.display === 'none') return false;
if (style.visibility !== 'visible') return false;
if ((style.opacity as any) === 0) return false;
if (
elem.offsetWidth +
elem.offsetHeight +
elem.getBoundingClientRect().height +
elem.getBoundingClientRect().width === 0
) return false;
const elementPoints = {
center: {
x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
y: elem.getBoundingClientRect().top + elem.offsetHeight / 2,
},
topLeft: {
x: elem.getBoundingClientRect().left,
y: elem.getBoundingClientRect().top,
},
topRight: {
x: elem.getBoundingClientRect().right,
y: elem.getBoundingClientRect().top,
},
bottomLeft: {
x: elem.getBoundingClientRect().left,
y: elem.getBoundingClientRect().bottom,
},
bottomRight: {
x: elem.getBoundingClientRect().right,
y: elem.getBoundingClientRect().bottom,
},
};
const docWidth = document.documentElement.clientWidth || window.innerWidth;
const docHeight = document.documentElement.clientHeight || window.innerHeight;
if (elementPoints.topLeft.x > docWidth) return false;
if (elementPoints.topLeft.y > docHeight) return false;
if (elementPoints.bottomRight.x < 0) return false;
if (elementPoints.bottomRight.y < 0) return false;
for (let index in elementPoints) {
const point = elementPoints[index];
let pointContainer = document.elementFromPoint(point.x, point.y);
if (pointContainer !== null) {
do {
if (pointContainer === elem) return true;
} while (pointContainer = pointContainer.parentNode);
}
}
return false;
}
This may help : Hide the element by positioning it on far most left position and then check the offsetLeft property. If you want to use jQuery you can simply check the :visible selector and get the visibility state of the element.
HTML :
<div id="myDiv">Hello</div>
CSS :
<!-- for javaScript-->
#myDiv{
position:absolute;
left : -2000px;
}
<!-- for jQuery -->
#myDiv{
visibility:hidden;
}
javaScript :
var myStyle = document.getElementById("myDiv").offsetLeft;
if(myStyle < 0){
alert("Div is hidden!!");
}
jQuery :
if( $("#MyElement").is(":visible") == true )
{
alert("Div is visible!!");
}
jsFiddle