Controlla se l'elemento è visibile in DOM


378

Esiste un modo per verificare se un elemento è visibile in JS puro (no jQuery)?

Quindi, ad esempio, in questa pagina: Performance Bikes , se passi sopra le offerte (nel menu in alto), viene visualizzata una finestra di offerte, ma all'inizio non veniva mostrata. È nell'HTML ma non è visibile.

Quindi, dato un elemento DOM, come posso verificare se è visibile o no? Provai:

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

ma non sembra funzionare. Mi chiedo quali attributi dovrei controllare. Mi viene in mente:

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

Qualcun altro a cui potrei mancare?


1
Che non usa il display, usa la visibilità, quindi controlla la visibilità (nascosta o visibile). es:document.getElementById('snDealsPanel').style.visibility
PSL

PSL. Se vorrei fare questo in modo più generale, quali attributi devo controllare: visibilità, visualizzazione ...?
Hommer Smith,

Puoi renderlo generico a modo tuo, ma quello che sto dicendo è che usa la visibilità ispezionando l'elemento.
PSL,

Ecco il mio codice (no jquery) per questa domanda stackoverflow.com/a/22969337/2274995
Aleko

Il collegamento è interrotto e ciò rende la tua domanda non facile da capire. Si prega di ri-inquadrarlo.
Yogihosting

Risposte:


619

Secondo questa documentazione MDN , la offsetParentproprietà di un elemento ritornerà nullogni volta che essa, o uno dei suoi genitori, viene nascosto tramite la proprietà dello stile di visualizzazione. Assicurati solo che l'elemento non sia riparato. Uno script per verificare questo, se non ci sono position: fixed;elementi nella tua pagina, potrebbe apparire come:

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

D'altra parte, se non dispone di elementi di posizione fissa che potrebbero impigliarsi in questa ricerca, si tristemente (e lentamente) devono usare window.getComputedStyle(). La funzione in tal caso potrebbe essere:

// 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'opzione n. 2 è probabilmente un po 'più semplice poiché tiene conto di più casi limite, ma scommetto che è anche molto più lento, quindi se devi ripetere questa operazione molte volte, è meglio evitarla.


Wow, non scherzo. Imo non ci dovrebbero essere motivi per usare il secondo metodo come soluzione universale; nessuna pagina dovrebbe avere elementi fissi di cui il suo creatore non è esplicitamente a conoscenza, e si può semplicemente controllare quelli manualmente usando il metodo getComputedStyle () dopo aver eseguito prima il metodo offsetParent su tutti gli elementi.
AlexZ,

6
Inoltre, appena scoperto che el.offsetParentnon funzionava su IE9 per elementi non fissi. O almeno così sembra. (OK per IE11, però.) Quindi, getComputedStyledopo tutto, è andato avanti .
Nick,

1
@AlexZ Non sono sicuro che offsetParent fa davvero un riflusso nei browser di oggi, ma sì, un paio di anni fa, lo facevano, è quello che capisco dai rapporti. Si noti che jsPerf menziona solo la velocità di esecuzione, mentre il reflow riguarda il display. E i reflow rendono l'interfaccia utente scadente. Personalmente non cercherò la velocità per una routine che probabilmente viene chiamata 5/6 volte su una pagina.
Ethan,

2
ahimè! getComputedStylenon funziona correttamente: plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview Tuttavia, anche così offsetParent- forse una combinazione dei due dovrebbe essere usata?
guy mograbi,

2
per ie9 + ie10 puoi verificare se offsetParent = body per elementi non visibili.
SuperUberDuper

99

Tutte le altre soluzioni hanno rotto per qualche situazione per me ..

Vedi la risposta vincente rompendo a:

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

Alla fine, ho deciso che la soluzione migliore era $(elem).is(':visible')- tuttavia, questo non è javascript puro. è jquery ..

così ho dato una sbirciatina alla loro fonte e ho trovato quello che volevo

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

Questa è la fonte: https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js


11
Questo tornerà trueper un elemento convisibility:hidden
Yuval A.

9
@YuvalA .: Sì, perché l'elemento è ancora visibile. L'impostazione di un elemento su visibility:hiddennon mostra più alcun contenuto, ma richiede comunque la larghezza e l'altezza dell'elemento!
Jacob van Lingen,

4
@Michael puoi sfogliare facilmente il codice jQuery e se stai usando un IDE moderno (provalo in caso contrario) puoi saltare per correggere le parti del codice mentre usi jQuery o qualsiasi altra libreria. Puoi imparare molto mentre navighi su basi di codice di progetti open source.
Lukas Liesis,

53

Se sei interessato a visibile dall'utente:

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

Testato su (usando la terminologia della moka ):

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

un caso limite se l'elem è posizionato all'esterno della finestra, può essere catturato da "if (! pointContainer) return false;" controllo del primo punto Container
Jerry Deng

Se vuoi verificare se l'utente potrebbe vederlo, dovresti usare un scrollIntoViewdiritto ?! Questo è abbastanza costoso. C'è un altro modo intelligente?
Kim Kern

36

Questo può essere d'aiuto: Nascondi l'elemento posizionandolo nella posizione più a sinistra, quindi controlla la proprietà offsetLeft. Se vuoi usare jQuery puoi semplicemente selezionare il selettore : visible e ottenere lo stato di visibilità dell'elemento.

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


12
L'OP richiede una risposta no-jQuery.
Stephen Quan,

È stato modificato più tardi, immagino. Quando ho risposto non è stato menzionato nel thread.
Md. Ashaduzzaman,

2
@StephenQuan, ho aggiornato la risposta con entrambe le soluzioni jQuery e javaScript.
Md. Ashaduzzaman,

6
per l'esempio jQuery, l'avviso non dovrebbe dire "Div è visibile?"
Andrei Bazanov,

Non vorrei concludere che un elemento sia completamente nascosto solo perché il suo offsetLeft è inferiore a 0: cosa succede se è solo un piccolo numero di pixel inferiore a 0 e la sua parte destra è visibile? (Sono d'accordo che sembrerebbe un disegno sciocco, ma al giorno d'oggi non si sa mai con i web designer.) Probabilmente è meglio aggiungere la larghezza a offset Sinistra e vedere se il risultato è ancora inferiore a 0. Per ogni evenienza.
Silas S. Brown,

31

Usa lo stesso codice di jQuery:

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

Quindi, in una funzione:

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

Funziona come un fascino nel mio Win / IE10, Linux / Firefox.45, Linux / Chrome.52 ...

Mille grazie a jQuery senza jQuery!


Bello ma non copre gli elementi nascosti dall'overflow.
Alph.Dev,

bello ma perché !! (doppia negazione)?
Sunil Garg,

3
Per forzare il risultato come booleano. Come e.offsetWidthè un numero intero, !e.offsetWidthrestituirà falsese e.offsetWidthè maggiore di zero (l'elemento è visibile). Quindi l'aggiunta di un altro !come in !!e.offsetWidthrestituirà truese e.offsetWidthè maggiore di zero. È una scorciatoia per return e.offsetWidth > 0 ? true : falseo ovviamente return e.offsetWidth > 0.
Yvan,

16

Combinando un paio di risposte sopra:

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

Come ha detto AlexZ, questo potrebbe essere più lento di alcune delle altre opzioni se sai più specificamente cosa stai cercando, ma questo dovrebbe catturare tutti i principali modi in cui gli elementi sono nascosti.

Ma dipende anche da ciò che conta come visibile per te. Ad esempio, l'altezza di un div può essere impostata su 0px ma i contenuti sono ancora visibili a seconda delle proprietà di overflow. Oppure il contenuto di un div può essere reso dello stesso colore dello sfondo in modo che non sia visibile agli utenti ma sia comunque visualizzato sulla pagina. Oppure un div potrebbe essere spostato dallo schermo o nascosto dietro altri div, oppure i suoi contenuti potrebbero non essere visibili ma il bordo sarebbe ancora visibile. In una certa misura "visibile" è un termine soggettivo.


1
Bello, ma style.opacity, style.height e style.width restituiscono una stringa in modo che non funzioni! ==
Maslow

Un altro modo in cui un elemento può essere nascosto tramite lo stile è che il suo colore potrebbe corrispondere al colore di sfondo, oppure il suo indice z potrebbe essere inferiore rispetto ad altri elementi.
Nu Everest,

aggiungere display:nonea questo sarebbe fantastico. Una soluzione funzionante!
Gijo Varghese,

7

Ho una soluzione più performante rispetto alla soluzione getComputedStyle () di AlexZ quando si hanno elementi 'fissi' di posizione, se si è disposti a ignorare alcuni casi limite (controllare i commenti):

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

Nota a margine: a rigor di termini, la "visibilità" deve essere definita per prima. Nel mio caso, sto prendendo in considerazione un elemento visibile fintanto che posso eseguire tutti i metodi / proprietà DOM su di esso senza problemi (anche se l'opacità è 0 o la proprietà di visibilità CSS è 'nascosta' ecc.).


6

Se l'elemento è regolarmente visibile (display: block e visibillity: visible), ma alcuni container parent sono nascosti, allora possiamo usare clientWidth e clientHeight per verificarlo.

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

Plunker (clicca qui)


ele.style.visibility !== 'hidden'è ridondante qui. In tal caso, clientWidth e clientHeight saranno 0.
subdavis

5

Se stiamo solo raccogliendo i modi di base per rilevare la visibilità, non dimenticarmi:

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

E su come ottenere gli attributi:

element.getAttribute(attributename);

Quindi, nel tuo esempio:

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

Ma cosa? Qui non funziona. Guarda più da vicino e scoprirai che la visibilità non viene aggiornata come un attributo sull'elemento, ma utilizzando la styleproprietà. Questo è uno dei tanti problemi nel provare a fare quello che stai facendo. Tra gli altri: non puoi garantire che ci sia effettivamente qualcosa da vedere in un elemento, solo perché la sua visibilità, visualizzazione e opacità hanno tutti i valori corretti. Potrebbe ancora mancare di contenuto o potrebbe mancare di altezza e larghezza. Un altro oggetto potrebbe oscurarlo. Per maggiori dettagli, una rapida ricerca su Google rivela questo , e comprende anche una libreria per provare a risolvere il problema. (YMMV)

Dai un'occhiata a quanto segue, che sono possibili duplicati di questa domanda, con risposte eccellenti, tra cui alcune intuizioni del potente John Resig. Tuttavia, il tuo caso d'uso specifico è leggermente diverso da quello standard, quindi mi asterrò dal segnalare:

(MODIFICA: OP DICE CHE STA SCARICANDO LE PAGINE, NON CREARLE, COSÌ SOTTO NON È APPLICABILE) Un'opzione migliore? Associa la visibilità degli elementi alle proprietà del modello e fai sempre dipendere la visibilità da quel modello, proprio come fa Angular con ng-show. Puoi farlo usando qualsiasi strumento tu voglia: angolare, semplice JS, qualunque cosa. Meglio ancora, puoi cambiare l'implementazione del DOM nel tempo, ma sarai sempre in grado di leggere lo stato dal modello, anziché il DOM. Leggere la tua verità dal DOM è male. E lento. Molto meglio controllare il modello e fidarsi dell'implementazione per garantire che lo stato DOM rifletta il modello. (E utilizza i test automatici per confermare tale presupposto.)


Sto analizzando i siti, questo non è per il mio sito ... :)
Hommer Smith,

4

La risposta accettata non ha funzionato per me. Risposta per l'anno 2020 :

1) Il metodo (elem.offsetParent! == null) funziona bene in Firefox ma non in Chrome. Per Chrome "position: fixed;" renderà anche offsetParent restituito "null" anche l'elemento se visibile nella pagina.

demo:

//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>

puoi vedere questo megatest https://stackoverflow.com/a/11639664/4481831 ( eseguilo con più browser per vedere le differenze).

2) (getComputedStyle (elem) .display! == 'none') non funziona perché l'elemento può essere invisibile poiché una delle proprietà di visualizzazione dei genitori è impostata su none, getComputedStyle non lo rileva.

demo:

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) Il (elem.clientHeight! == 0) . Questo metodo non è influenzato dalla posizione fissa e controlla anche se i genitori elemento non sono visibili. Ma ha problemi con elementi semplici che non hanno un layout CSS, vedi di più qui

demo:

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) Il (elem.getClientRects (). Length! == 0) che sembrano superare i problemi dei precedenti 3 metodi. Tuttavia ha problemi con gli elementi che usano trucchi CSS (diversi da "display: none") per nascondersi nella pagina.

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>

CONCLUSIONE: Quindi quello che ti ho mostrato è che nessun metodo è perfetto. Per effettuare un controllo di visibilità adeguato è necessario utilizzare una combinazione degli ultimi 3 metodi.


3

Solo per riferimento, va notato che getBoundingClientRect()può funzionare in alcuni casi.

Ad esempio, un semplice controllo che l'elemento è nascosto usando display: nonepotrebbe apparire in qualche modo simile a questo:

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

Questo è utile anche perché copre anche larghezza zero, altezza zero e position: fixedcasi. Tuttavia, non deve riportare elementi nascosti con opacity: 0o visibility: hidden(ma nessuno dei due lo farebbe offsetParent).


La migliore risposta per me ... semplice ed efficace. E nessun singolo voto dopo 3 anni! Continua a mostrare il valore della "saggezza della folla". La mia versione: var isVisible = el => (r => r.width && r.height)(el.getBoundingClientRect());. Allora posso filtrata array di elementi nel modo seguente: $$(sel).filter(isVisible).
7vujy0f0hy


Questo non funziona se visibile all'utente .... se scorri via rimarrà vero
Ray Foss,

3

Quindi quello che ho trovato è il metodo più fattibile:

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

Questo si basa su questi fatti:

  • Un display: noneelemento (anche nidificato) non ha né larghezza né altezza.
  • visiblityè hiddenanche per gli elementi nidificati.

Quindi non è necessario eseguire test offsetParento eseguire il looping nella struttura DOM per verificare quale padre ha visibility: hidden. Questo dovrebbe funzionare anche in IE 9.

Si potrebbe obiettare se opacity: 0e anche gli elementi collassati (ha una larghezza ma non un'altezza - o viceversa) non sono realmente visibili. Ma poi di nuovo non sono per così dire nascosti.


3

Una piccola aggiunta alla risposta di Ohad Navon.

Se il centro dell'elemento appartiene a un altro elemento, non lo troveremo.

Quindi, per essere sicuri che uno dei punti dell'elemento sia visibile

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

3

Migliorare la risposta di @Guy Messika sopra , rompere e restituire false se il punto centrale 'X è <0 è errato in quanto l'elemento lato destro può andare nella vista. ecco una soluzione:

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

2

Il codice jQuery da http://code.jquery.com/jquery-1.11.1.js ha un parametro 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 );
};

Quindi sembra che ci sia un controllo extra relativo al documento del proprietario

Mi chiedo se questo cattura davvero i seguenti casi:

  1. Elementi nascosti dietro altri elementi basati su zIndex
  2. Elementi con trasparenza piena che li rendono invisibili
  3. Elementi posizionati fuori dallo schermo (ovvero a sinistra: -1000 px)
  4. Elementi con visibilità: nascosti
  5. Elementi con display: nessuno
  6. Elementi senza testo o elementi secondari visibili
  7. Elementi con altezza o larghezza impostati su 0

0

Ecco il codice che ho scritto per trovare l'unico visibile tra alcuni elementi simili e restituire il valore del suo attributo "class" senza 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");
    }
  }

0

Questo è quello che ho fatto:

HTML e CSS: reso nascosto l'elemento per impostazione predefinita

<html>
<body>

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

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

</body>
</html> 

JavaScript: aggiunto un codice per verificare se la visibilità è nascosta o meno:

<script>
function myFunction() {
   if ( document.getElementById("demo").style.visibility === "hidden"){
   document.getElementById("demo").style.visibility = "visible";
   }
   else document.getElementById("demo").style.visibility = "hidden";
}
</script>

-1

Questo è un modo per determinarlo per tutte le proprietà css inclusa 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');
}

Funziona con qualsiasi proprietà CSS ed è molto versatile e affidabile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.