15

I have elements like below

<div class="one">send Message</div>

<div class="one">send Message</div>

<div class="one">send Message</div>

I have a web page where there is send Message buttons like above, in which only one button is visible at a time.Other two buttons are hidden via some javascript codes.So for example if 2nd button is visible , I should be able to get only that element.

So my code will be something like

document.querySelector(".one:visible");

In jquery the code is $(".one:visible"); , which works fine , But I need to know how to do this via pure javascript.

Vishnu
  • 2,372
  • 6
  • 36
  • 58
  • 3
    `Other two buttons are hidden via some javascript codes` how are they hidden exactly? – Jaromanda X Jun 18 '17 at 05:56
  • I dont know , I am trying this in developer console , in some one else website , where there are list of users profiles with dropdown , when I click drop down send message list appears – Vishnu Jun 18 '17 at 06:07
  • `I dont know` - well, that's possibly a problem – Jaromanda X Jun 18 '17 at 06:08
  • Its facebook.com , they have like 100 javascript codes – Vishnu Jun 18 '17 at 06:09
  • To see **how** the element is being hidden, go into the DOM inspector, search (Ctrl-F) for `.one` to find the elements with that class, then view their properties to see if it's `display: none` or something else. –  Jun 18 '17 at 06:44
  • "How to check if element is visible after scrolling?" was helpful for me: https://stackoverflow.com/a/488073/470749 – Ryan Jun 03 '21 at 20:14

6 Answers6

14

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'))
}
Koby Douek
  • 16,156
  • 19
  • 74
  • 103
  • Could also be `visibility: hidden` or some other mechanism. – Sirko Jun 18 '17 at 05:58
  • jquery does not use visibility check for :visible – gauravmuk Jun 18 '17 at 06:02
  • if height or width is zero, is the element technically visible? – Jaromanda X Jun 18 '17 at 06:09
  • @JaromandaX The OP was referring to `visible` which for my understadning stands for `display` of `visibility`. I can see your comments to the PO which is not 100% on what he needs, I'm keeping an eye. – Koby Douek Jun 18 '17 at 06:11
  • 3
    I don't believe this will work in the case of the `my-element` element in `
    Hi Bob
    `, because the computed style on `my-element` will not be `display: none`, yet it will be hidden because it's parent has `display: none`.
    –  Jun 18 '17 at 06:39
  • This works really well, just watch if you use visibility === 'collapse' and add that to the function. – SaintFrag May 10 '21 at 14:38
7

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.

Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265
hbrade
  • 119
  • 1
  • 2
  • If you need older browser support I would recommend also using this Polyfill for `Array.from` and `.filter`: https://polyfill.io/v3/polyfill.min.js?features=Array.from%2CArray.prototype.filter. If you arent using something like babel to transpile your arrow functions then you'll need to get rid of the arrow function. – maxshuty Jan 11 '20 at 14:04
5

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)

3
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.

gauravmuk
  • 1,606
  • 14
  • 20
2

If you're using the hidden attribute :

document.querySelector(".one:not([hidden])");
Mojimi
  • 2,561
  • 9
  • 52
  • 116
0

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.

Dylan Maxey
  • 976
  • 10
  • 9