Vérifier si l'élément est visible dans DOM

378

Existe-t-il un moyen de vérifier si un élément est visible en JS pur (pas de jQuery)?

Ainsi, par exemple, dans cette page: Performance Bikes , si vous survolez Deals (dans le menu supérieur), une fenêtre d'offres apparaît, mais au début, elle n'était pas affichée. C'est dans le HTML mais ce n'est pas visible.

Donc, étant donné un élément DOM, comment puis-je vérifier s'il est visible ou non? J'ai essayé:

window.getComputedStyle(my_element)['display']);

mais cela ne semble pas fonctionner. Je me demande quels attributs dois-je vérifier. Cela me vient à l'esprit:

display !== 'none'
visibility !== 'hidden'

Y en a-t-il d'autres qui pourraient me manquer?

Hommer Smith
la source
1
Cela n'utilise pas l'affichage, il utilise la visibilité, alors vérifiez la visibilité (cachée ou visible). ex:document.getElementById('snDealsPanel').style.visibility
PSL
PSL. Si je souhaite faire cela de manière plus générale, quels attributs dois-je vérifier: visibilité, affichage ...?
Hommer Smith
Vous pouvez le rendre générique à votre manière, mais ce que je dis, c'est qu'il utilise la visibilité pour inspecter l'élément.
PSL
Voici mon code (pas de jquery) pour cette question stackoverflow.com/a/22969337/2274995
Aleko
Le lien est rompu, ce qui rend votre question difficile à comprendre. Veuillez le recadrer.
yogihosting le

Réponses:

619

Selon cette documentation MDN , la offsetParentpropriété d' un élément sera renvoyée nullchaque fois que lui, ou l'un de ses parents, est masqué via la propriété de style d'affichage. Assurez-vous simplement que l'élément n'est pas fixe. Un script pour vérifier cela, si vous n'avez aucun position: fixed;élément sur votre page, pourrait ressembler à:

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
    return (el.offsetParent === null)
}

D'autre part, si vous n'avez la position des éléments fixes qui pourraient se coincer dans cette recherche, vous malheureusement (et lentement) doivent utiliser . Dans ce cas, la fonction pourrait être:window.getComputedStyle()

// 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')
}

L'option # 2 est probablement un peu plus simple car elle représente plus de cas marginaux, mais je parie que c'est beaucoup plus lent aussi, donc si vous devez répéter cette opération plusieurs fois, mieux vaut probablement l'éviter.

AlexZ
la source
Wow sans blague. Imo, il ne devrait y avoir aucune raison d'utiliser la deuxième méthode comme solution universelle; aucune page ne doit avoir d'éléments fixes que son créateur ne connaît pas explicitement, et on peut simplement les vérifier manuellement en utilisant la méthode getComputedStyle () après avoir exécuté la méthode offsetParent sur tous les éléments en premier.
AlexZ
6
Aussi FYI, vient de découvrir que el.offsetParentne fonctionnait pas sur IE9 pour les éléments non fixes. Ou du moins, semble-t-il. (OK pour IE11, cependant.) Il en va de même getComputedStyleaprès tout.
Nick
1
@AlexZ Je ne sais pas si offsetParent fait vraiment une redistribution dans les navigateurs d'aujourd'hui, mais oui il y a quelques années, ils le faisaient, c'est ce que je comprends des rapports. Notez que le jsPerf ne mentionne que la vitesse d'exécution, tandis que la refusion concerne l'affichage. Et la redistribution rend l'interface utilisateur pauvre. Personnellement, je n'irai pas pour la vitesse pour une routine qui est probablement appelée 5/6 fois sur une page.
Ethan
2
Hélas! getComputedStylene fonctionne pas correctement: plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview Cependant, il en va de même offsetParent- peut-être qu'une combinaison des deux devrait être utilisée?
guy mograbi
2
pour ie9 + ie10, vous pouvez vérifier si offsetParent = body pour les éléments non visibles.
SuperUberDuper
99

Toutes les autres solutions se sont cassées pour une situation pour moi ..

Voir la réponse gagnante se briser à:

http://plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview

Finalement, j'ai décidé que la meilleure solution était $(elem).is(':visible')- cependant, ce n'est pas du pur javascript. c'est jquery ..

alors j'ai jeté un œil à leur source et j'ai trouvé ce que je voulais

jQuery.expr.filters.visible = function( elem ) {
    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

Ceci est la source: https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js

guy mograbi
la source
11
Cela reviendra truepour un élément avecvisibility:hidden
Yuval A.
9
@YuvalA .: Oui parce que l'élément est toujours visible. Définir un élément pour visibility:hiddenn'afficher plus de contenu, mais prend toujours la largeur et la hauteur de l'élément!
Jacob van Lingen
4
@Michael, vous pouvez facilement parcourir le code jQuery et si vous utilisez un IDE moderne (essayez-le sinon), vous pouvez sauter pour corriger les parties de code tout en utilisant jQuery ou toute autre lib. Vous pouvez en apprendre beaucoup en parcourant les bases de code des projets open source.
Lukas Liesis
53

Si l'utilisateur est intéressé par le visible:

function isVisible(elem) {
    if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
    const style = getComputedStyle(elem);
    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if (style.opacity < 0.1) return false;
    if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0) {
        return false;
    }
    const elemCenter   = {
        x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
        y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
    };
    if (elemCenter.x < 0) return false;
    if (elemCenter.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
    if (elemCenter.y < 0) return false;
    if (elemCenter.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
    let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y);
    do {
        if (pointContainer === elem) return true;
    } while (pointContainer = pointContainer.parentNode);
    return false;
}

Testé sur (en utilisant la terminologie mocha ):

describe.only('visibility', function () {
    let div, visible, notVisible, inViewport, leftOfViewport, rightOfViewport, aboveViewport,
        belowViewport, notDisplayed, zeroOpacity, zIndex1, zIndex2;
    before(() => {
        div = document.createElement('div');
        document.querySelector('body').appendChild(div);
        div.appendChild(visible = document.createElement('div'));
        visible.style       = 'border: 1px solid black; margin: 5px; display: inline-block;';
        visible.textContent = 'visible';
        div.appendChild(inViewport = visible.cloneNode(false));
        inViewport.textContent = 'inViewport';
        div.appendChild(notDisplayed = visible.cloneNode(false));
        notDisplayed.style.display = 'none';
        notDisplayed.textContent   = 'notDisplayed';
        div.appendChild(notVisible = visible.cloneNode(false));
        notVisible.style.visibility = 'hidden';
        notVisible.textContent      = 'notVisible';
        div.appendChild(leftOfViewport = visible.cloneNode(false));
        leftOfViewport.style.position = 'absolute';
        leftOfViewport.style.right = '100000px';
        leftOfViewport.textContent = 'leftOfViewport';
        div.appendChild(rightOfViewport = leftOfViewport.cloneNode(false));
        rightOfViewport.style.right       = '0';
        rightOfViewport.style.left       = '100000px';
        rightOfViewport.textContent = 'rightOfViewport';
        div.appendChild(aboveViewport = leftOfViewport.cloneNode(false));
        aboveViewport.style.right       = '0';
        aboveViewport.style.bottom       = '100000px';
        aboveViewport.textContent = 'aboveViewport';
        div.appendChild(belowViewport = leftOfViewport.cloneNode(false));
        belowViewport.style.right       = '0';
        belowViewport.style.top       = '100000px';
        belowViewport.textContent = 'belowViewport';
        div.appendChild(zeroOpacity = visible.cloneNode(false));
        zeroOpacity.textContent   = 'zeroOpacity';
        zeroOpacity.style.opacity = '0';
        div.appendChild(zIndex1 = visible.cloneNode(false));
        zIndex1.textContent = 'zIndex1';
        zIndex1.style.position = 'absolute';
        zIndex1.style.left = zIndex1.style.top = zIndex1.style.width = zIndex1.style.height = '100px';
        zIndex1.style.zIndex = '1';
        div.appendChild(zIndex2 = zIndex1.cloneNode(false));
        zIndex2.textContent = 'zIndex2';
        zIndex2.style.left = zIndex2.style.top = '90px';
        zIndex2.style.width = zIndex2.style.height = '120px';
        zIndex2.style.backgroundColor = 'red';
        zIndex2.style.zIndex = '2';
    });
    after(() => {
        div.parentNode.removeChild(div);
    });
    it('isVisible = true', () => {
        expect(isVisible(div)).to.be.true;
        expect(isVisible(visible)).to.be.true;
        expect(isVisible(inViewport)).to.be.true;
        expect(isVisible(zIndex2)).to.be.true;
    });
    it('isVisible = false', () => {
        expect(isVisible(notDisplayed)).to.be.false;
        expect(isVisible(notVisible)).to.be.false;
        expect(isVisible(document.createElement('div'))).to.be.false;
        expect(isVisible(zIndex1)).to.be.false;
        expect(isVisible(zeroOpacity)).to.be.false;
        expect(isVisible(leftOfViewport)).to.be.false;
        expect(isVisible(rightOfViewport)).to.be.false;
        expect(isVisible(aboveViewport)).to.be.false;
        expect(isVisible(belowViewport)).to.be.false;
    });
});
Ohad Navon
la source
un cas de bord si l'elem est positionné en dehors de la fenêtre, peut être attrapé par "if (! pointContainer) return false;" vérification du premier pointConteneur
Jerry Deng
Si vous voulez vérifier si l'utilisateur peut le voir, vous devez utiliser un scrollIntoViewdroit?! C'est assez cher. Existe-t-il un autre moyen intelligent?
Kim Kern
36

Cela peut aider: Masquer l'élément en le positionnant à l'extrême gauche, puis vérifier la propriété offsetLeft. Si vous souhaitez utiliser jQuery, vous pouvez simplement vérifier le sélecteur : visible et obtenir l'état de visibilité de l'élément.

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

Md. Ashaduzzaman
la source
12
L'OP demande une réponse no-jQuery.
Stephen Quan
Il a été édité plus tard, je suppose. Quand j'ai répondu, ce n'était pas mentionné dans le fil.
Md. Ashaduzzaman
2
@StephenQuan, j'ai mis à jour la réponse avec la solution jQuery et javaScript.
Md. Ashaduzzaman
6
pour l'exemple jQuery, l'alerte ne devrait-elle pas indiquer "Div est visible?"
Andrei Bazanov
Je ne voudrais pas conclure qu'un élément est entièrement masqué simplement parce que sa valeur offsetLeft est inférieure à 0: que faire si ce n'est qu'un petit nombre de pixels inférieur à 0 et que sa partie droite est visible? (Je suis d'accord que cela semblerait un design stupide, mais on ne sait jamais avec les concepteurs de sites Web de nos jours.) Il est probablement préférable d'ajouter la largeur à offsetLeft et de voir si le résultat est toujours inférieur à 0. Juste au cas où.
Silas S. Brown
31

Utilisez le même code que jQuery:

jQuery.expr.pseudos.visible = function( elem ) {
    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

Donc, dans une fonction:

function isVisible(e) {
    return !!( e.offsetWidth || e.offsetHeight || e.getClientRects().length );
}

Fonctionne comme un charme dans mon Win / IE10, Linux / Firefox.45, Linux / Chrome.52 ...

Un grand merci à jQuery sans jQuery!

Yvan
la source
Bien mais ne couvre pas les éléments cachés par le débordement.
Alph.Dev
sympa mais pourquoi !! (double négation)?
Sunil Garg
3
Pour forcer le résultat comme booléen. Comme e.offsetWidthc'est un entier, !e.offsetWidthretournera falsesi e.offsetWidthest supérieur à zéro (l'élément est visible). Donc, ajouter un autre !comme dans !!e.offsetWidthretournera truesi e.offsetWidthest supérieur à zéro. C'est un raccourci pour return e.offsetWidth > 0 ? true : falseou évidemment return e.offsetWidth > 0.
Yvan
16

Combiner quelques réponses ci-dessus:

function isVisible (ele) {
    var style = window.getComputedStyle(ele);
    return  style.width !== "0" &&
    style.height !== "0" &&
    style.opacity !== "0" &&
    style.display!=='none' &&
    style.visibility!== 'hidden';
}

Comme l'a dit AlexZ, cela peut être plus lent que certaines de vos autres options si vous savez plus précisément ce que vous recherchez, mais cela devrait comprendre toutes les principales façons dont les éléments sont masqués.

Mais cela dépend aussi de ce qui compte pour vous. Par exemple, la hauteur d'une div peut être définie sur 0px mais le contenu reste visible en fonction des propriétés de débordement. Ou le contenu d'un div pourrait être de la même couleur que l'arrière-plan afin qu'il ne soit pas visible pour les utilisateurs mais toujours rendu sur la page. Ou un div pourrait être déplacé hors de l'écran ou caché derrière d'autres div, ou son contenu pourrait être non visible mais la bordure toujours visible. Dans une certaine mesure, «visible» est un terme subjectif.

Matthieu
la source
1
Bien, mais style.opacity, style.height et style.width renvoient une chaîne afin qu'elle ne fonctionne pas avec! ==
Maslow
Un autre moyen de masquer un élément via le style consiste à ce que sa couleur corresponde à la couleur d'arrière-plan ou que son index z soit inférieur à celui des autres éléments.
nu everest
ajouter display:noneà cela serait formidable. Une bonne solution de travail!
Gijo Varghese
7

J'ai une solution plus performante par rapport à la solution getComputedStyle () d'AlexZ quand on a des éléments 'fixes' de position, si on veut ignorer certains cas de bord (vérifier les commentaires):

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;
}

Note complémentaire: à strictement parler, la "visibilité" doit être définie en premier. Dans mon cas, je considère un élément visible tant que je peux exécuter toutes les méthodes / propriétés DOM dessus sans problème (même si l'opacité est 0 ou la propriété de visibilité CSS est «cachée», etc.).

Munawwar
la source
6

Si l'élément est régulièrement visible (display: block et visibillity: visible), mais qu'un conteneur parent est masqué, nous pouvons utiliser clientWidth et clientHeight pour vérifier cela.

function isVisible (ele) {
  return  ele.clientWidth !== 0 &&
    ele.clientHeight !== 0 &&
    ele.style.opacity !== 0 &&
    ele.style.visibility !== 'hidden';
}

Plunker (cliquez ici)

Vlada
la source
ele.style.visibility !== 'hidden'est redondant ici. Dans ce cas, clientWidth et clientHeight seront 0.
subdavis
5

Si nous ne faisons que collecter des méthodes de base pour détecter la visibilité, je ne vais pas oublier:

opacity > 0.01; // probably more like .1 to actually be visible, but YMMV

Et quant à la façon d'obtenir des attributs:

element.getAttribute(attributename);

Donc, dans votre exemple:

document.getElementById('snDealsPanel').getAttribute('visibility');

Mais quoi? Ça ne marche pas ici. Regardez de plus près et vous constaterez que la visibilité est mise à jour non pas en tant qu'attribut sur l'élément, mais en utilisant la stylepropriété. C'est l'un des nombreux problèmes que vous rencontrez lorsque vous essayez de faire ce que vous faites. Entre autres: vous ne pouvez pas garantir qu'il y a réellement quelque chose à voir dans un élément, simplement parce que sa visibilité, son affichage et son opacité ont tous les bonnes valeurs. Il peut encore manquer de contenu ou manquer de hauteur et de largeur. Un autre objet pourrait l'obscurcir. Pour plus de détails, une recherche rapide sur Google révèle ce , et inclut même une bibliothèque pour essayer de résoudre le problème. (YMMV)

Consultez les éléments suivants, qui sont des doublons possibles de cette question, avec d'excellentes réponses, y compris quelques aperçus du puissant John Resig. Cependant, votre cas d'utilisation spécifique est légèrement différent de celui standard, donc je m'abstiendrai de signaler:

(MODIFICATION: OP DIT QU'IL PERMET DE RETIRER DES PAGES, PAS LES CRÉER, DONC CI-DESSOUS N'EST PAS APPLICABLE) Une meilleure option? Liez la visibilité des éléments aux propriétés du modèle et toujours rendre la visibilité dépendante de ce modèle, tout comme Angular le fait avec ng-show. Vous pouvez le faire en utilisant n'importe quel outil que vous voulez: JS angulaire, simple, peu importe. Mieux encore, vous pouvez changer l'implémentation DOM au fil du temps, mais vous pourrez toujours lire l'état du modèle, au lieu du DOM. Lire votre vérité depuis le DOM est mauvais. Et lent. Il est préférable de vérifier le modèle et de faire confiance à votre implémentation pour vous assurer que l'état DOM reflète le modèle. (Et utilisez des tests automatisés pour confirmer cette hypothèse.)

XML
la source
Je suis en train d'analyser des sites, ce n'est pas pour mon propre site ... :)
Hommer Smith
5

La réponse acceptée n'a pas fonctionné pour moi. Réponse de l'an 2020 :

1) La méthode (elem.offsetParent! == null) fonctionne très bien dans Firefox mais pas dans Chrome. Pour Chrome "position: fixed;" fera également offsetParent retourner "null" même l'élément s'il est visible dans la page.

Démo:

//different results in Chrome and Firefox
console.log(document.querySelector('#hidden1').offsetParent); //null Chrome & Firefox
console.log(document.querySelector('#fixed1').offsetParent); //null in Chrome, not null in Firefox
    <div id="hidden1" style="display:none;"></div>
    <div id="fixed1" style="position:fixed;"></div>

vous pouvez voir ce type de mégatest https://stackoverflow.com/a/11639664/4481831 (exécutez-le avec plusieurs navigateurs pour voir les différences).

2) Le (getComputedStyle (elem) .display! == 'none') ne fonctionne pas car l'élément peut être invisible car l'une des propriétés d'affichage des parents est définie sur none, getComputedStyle ne l'attrapera pas.

Démo:

var child1 = document.querySelector('#child1');
console.log(getComputedStyle(child1).display);
//child will show "block" instead of "none"
<div id="parent1" style="display:none;">
  <div id="child1" style="display:block"></div>
</div>

3) Le (elem.clientHeight! == 0) . Cette méthode n'est pas influencée par la position fixe et vérifie également si les parents d'élément ne sont pas visibles. Mais il a des problèmes avec des éléments simples qui n'ont pas de disposition CSS, voir plus ici

Démo:

console.log(document.querySelector('#div1').clientHeight); //not zero
console.log(document.querySelector('#span1').clientHeight); //zero
<div id="div1">test1 div</div>
<span id="span1">test2 span</span>

4) Les (elem.getClientRects (). Length! == 0) qui semblent dépasser les problèmes des 3 méthodes précédentes. Cependant, il a des problèmes avec les éléments qui utilisent des astuces CSS (autres que "display: none") pour se cacher dans la page.

console.log(document.querySelector('#notvisible1').getClientRects().length);
console.log(document.querySelector('#notvisible1').clientHeight);
console.log(document.querySelector('#notvisible2').getClientRects().length);
console.log(document.querySelector('#notvisible2').clientHeight);
console.log(document.querySelector('#notvisible3').getClientRects().length);
console.log(document.querySelector('#notvisible3').clientHeight);
<div id="notvisible1" style="height:0; overflow:hidden; background-color:red;">not visible 1</div>

<div id="notvisible2" style="visibility:hidden; background-color:yellow;">not visible 2</div>

<div id="notvisible3" style="opacity:0; background-color:blue;">not visible 3</div>

CONCLUSION: Donc, ce que je vous ai montré, c'est qu'aucune méthode n'est parfaite. Pour effectuer une vérification de visibilité correcte, vous devez utiliser une combinaison des 3 dernières méthodes.

crisc82
la source
3

Juste pour la référence, il convient de noter que cela getBoundingClientRect()peut fonctionner dans certains cas.

Par exemple, une simple vérification que l'élément est masqué à l'aide display: nonepourrait ressembler à ceci:

var box = element.getBoundingClientRect();
var visible = box.width && box.height;

Ceci est également pratique car il couvre également la largeur zéro, la hauteur zéro et les position: fixedétuis. Cependant, il ne doit pas signaler les éléments cachés avec opacity: 0ou visibility: hidden(mais aucun ne le ferait offsetParent).

incarner
la source
La meilleure réponse pour moi ... simple et efficace. Et pas de vote positif après 3 ans! Continue à montrer la valeur de la «sagesse de la foule». Ma version: var isVisible = el => (r => r.width && r.height)(el.getBoundingClientRect());. Ensuite , je peux filtrer les tableaux d'éléments de la façon suivante: $$(sel).filter(isVisible).
7vujy0f0hy
Je trouve que c'est la solution la plus simple developer.mozilla.org/en-US/docs/Web/API/Element/…
Marian07
Cela ne fonctionne pas lorsqu'il est visible par l'utilisateur .... si vous faites défiler, cela restera vrai
Ray Foss
3

Donc, ce que j'ai trouvé est la méthode la plus pratique:

function visible(elm) {
  if(!elm.offsetHeight && !elm.offsetWidth) { return false; }
  if(getComputedStyle(elm).visibility === 'hidden') { return false; }
  return true;
}

Ceci est construit sur ces faits:

  • Un display: noneélément (même imbriqué) n'a ni largeur ni hauteur.
  • visiblityest hiddenmême pour les éléments imbriqués.

Donc pas besoin de tester offsetParentou de boucler dans l'arborescence DOM pour tester quel parent a visibility: hidden. Cela devrait fonctionner même dans IE 9.

Vous pourriez discuter si opacity: 0et les éléments effondrés (a une largeur mais pas de hauteur - ou vice versa) ne sont pas vraiment visibles non plus. Mais là encore, ils ne sont pas pour autant cachés.

Tokimon
la source
3

Un petit ajout à la réponse d'Ohad Navon.

Si le centre de l'élément appartient à un autre élément, nous ne le trouverons pas.

Donc, pour vous assurer que l'un des points de l'élément est visible

function isElementVisible(elem) {
    if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
    const style = getComputedStyle(elem);
    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if (style.opacity === 0) return false;
    if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0) {
        return false;
    }
    var elementPoints = {
        'center': {
            x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
            y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
        },
        'top-left': {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().top
        },
        'top-right': {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().top
        },
        'bottom-left': {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().bottom
        },
        'bottom-right': {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().bottom
        }
    }

    for(index in elementPoints) {
        var point = elementPoints[index];
        if (point.x < 0) return false;
        if (point.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
        if (point.y < 0) return false;
        if (point.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
        let pointContainer = document.elementFromPoint(point.x, point.y);
        if (pointContainer !== null) {
            do {
                if (pointContainer === elem) return true;
            } while (pointContainer = pointContainer.parentNode);
        }
    }
    return false;
}
Guy Messika
la source
3

Améliorer la réponse de @Guy Messika ci - dessus , casser et retourner faux si le point central 'X est <0 est faux car l'élément de droite peut entrer dans la vue. voici une solution:

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;
}
Israël
la source
2

Le code jQuery de http://code.jquery.com/jquery-1.11.1.js a un paramètre isHidden

var isHidden = function( elem, el ) {
    // isHidden might be called from jQuery#filter function;
    // in that case, element will be second argument
    elem = el || elem;
    return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
};

Il semble donc qu'il y ait une vérification supplémentaire liée au document du propriétaire

Je me demande si cela attrape vraiment les cas suivants:

  1. Éléments cachés derrière d'autres éléments basés sur zIndex
  2. Éléments avec transparence totale les rendant invisibles
  3. Éléments positionnés hors écran (ie à gauche: -1000 px)
  4. Éléments avec visibilité: caché
  5. Éléments avec affichage: aucun
  6. Éléments sans texte visible ni sous-éléments
  7. Éléments dont la hauteur ou la largeur est définie sur 0
Scott Izu
la source
0

Voici le code que j'ai écrit pour trouver le seul visible parmi quelques éléments similaires et retourner la valeur de son attribut "class" sans jQuery:

  // Build a NodeList:
  var nl = document.querySelectorAll('.myCssSelector');

  // convert it to array:
  var myArray = [];for(var i = nl.length; i--; myArray.unshift(nl[i]));

  // now find the visible (= with offsetWidth more than 0) item:
  for (i =0; i < myArray.length; i++){
    var curEl = myArray[i];
    if (curEl.offsetWidth !== 0){
      return curEl.getAttribute("class");
    }
  }
non précisé
la source
0

C'est ce que j'ai fait:

HTML et CSS: rendu l'élément caché par défaut

<html>
<body>

<button onclick="myFunction()">Click Me</button>

<p id="demo" style ="visibility: hidden;">Hello World</p> 

</body>
</html> 

JavaScript: Ajout d'un code pour vérifier si la visibilité est masquée ou non:

<script>
function myFunction() {
   if ( document.getElementById("demo").style.visibility === "hidden"){
   document.getElementById("demo").style.visibility = "visible";
   }
   else document.getElementById("demo").style.visibility = "hidden";
}
</script>
Ajas Jansher
la source
-1

C'est un moyen de le déterminer pour toutes les propriétés CSS, y compris la visibilité:

html:

<div id="element">div content</div>

css:

#element
{
visibility:hidden;
}

javascript:

var element = document.getElementById('element');
 if(element.style.visibility == 'hidden'){
alert('hidden');
}
else
{
alert('visible');
}

Il fonctionne pour n'importe quelle propriété CSS et est très polyvalent et fiable.

William Green
la source