I have elements like below
send Message
send Message
sen
var $el = document.querySelectorAll('.one');
var visibleElements;
for (var i = 0; i < $el.length; i++) {
var currentElement = $el[i];
var $style = window.getComputedStyle(currentElement, null);
if (!currentElement) {
return false;
} else if (!$style) {
return false;
} else if ($style.display === 'none') {
return false;
} else {
visibleElements.push(currentElement);
}
}
First we get all the elements using document querySelectorAll. Then, we need to iterate over all the elements. To get the style, use getComputedStyle.
After that :visible check only for display and we do it the same way.
A more comprehensive approach:
function isVisible(el) {
while (el) {
if (el === document) {
return true;
}
var $style = window.getComputedStyle(el, null);
if (!el) {
return false;
} else if (!$style) {
return false;
} else if ($style.display === 'none') {
return false;
} else if ($style.visibility === 'hidden') {
return false;
} else if (+$style.opacity === 0) {
return false;
} else if (($style.display === 'block' || $style.display === 'inline-block') &&
$style.height === '0px' && $style.overflow === 'hidden') {
return false;
} else {
return $style.position === 'fixed' || isVisible(el.parentNode);
}
}
}
This would check for any possible way an element could be visible in the dom to my knowledge minus the z-index cases.
So all jQuery's :visible
selector does is check the display property.
If that's all you want, this is all you'd need.
(window.getComputedStyle(el).getPropertyValue('display') !== 'none')
However, this is lacking in many use cases. If you seek a more comprehensive solution, keep reading.
Both Element.getBoundingClientRect() and window.getComputedStyle() are useful for determining if the element is visible and in the viewport.
You can't use getBoundingRect() alone to determine the visibility, and while you could use getComputedStyle() solely, it's not the optimal solution in terms of performance.
Both of these functions used in conjunction with each other is the best option (around 22% faster than getComputedStyle() alone.
function inViewport(els) {
let matches = [],
elCt = els.length;
for (let i=0; i<elCt; ++i) {
let el = els[i],
b = el.getBoundingClientRect(), c;
if (b.width > 0 && b.height > 0 &&
b.left+b.width > 0 && b.right-b.width < window.outerWidth &&
b.top+b.height > 0 && b.bottom-b.width < window.outerHeight &&
(c = window.getComputedStyle(el)) &&
c.getPropertyValue('visibility') === 'visible' &&
c.getPropertyValue('opacity') !== 'none') {
matches.push(el);
}
}
return matches;
}
With a usage example of...
var els = document.querySelectorAll('.one'),
visibleEls = inViewport(els);
This ensures that the display is not set to "none", the visibility is "visible", the width and height are greater than 0, and the element is within the bounds of the viewport.
Here's something you can use, pure Javascript:
// Get all elements on the page (change this to another DOM element if you want)
var all = document.getElementsByTagName("*");
for (var i = 0, max = all.length; i < max; i++) {
if (isHidden(all[i]))
// hidden
else
// visible
}
function isHidden(el) {
var style = window.getComputedStyle(el);
return ((style.display === 'none') || (style.visibility === 'hidden'))
}
I have something shorter:
Array.from(document.querySelectorAll('.one')).filter(s =>
window.getComputedStyle(s).getPropertyValue('display') != 'none'
);
Returns all elements with attribute display
block
set.
If you're using the hidden
attribute :
document.querySelector(".one:not([hidden])");
Use getBoundingClientRect
. It will return height and width of zero if the element is not in the DOM, or is not displayed.
Note that this cannot be used to determine if an element is not visible due to visibility: hidden
or opacity: 0
. AFAIK this behavior is identical to the jQuery :visible
"selector". Apparently jQuery uses offsetHeight
and offsetWidth
of zero to check for non-visibility.
This solution will also not check if the item is not visible due to being off the screen (although you could check that easily enough), or if the element is hidden behind some other element.
See also Detect if an element is visible (without using jquery)