Überprüfen Sie, ob das Element im DOM sichtbar ist

377

Kann ich auf irgendeine Weise überprüfen, ob ein Element in reinem JS sichtbar ist (keine jQuery)?

So wird beispielsweise auf dieser Seite: Performance Bikes , wenn Sie mit der Maus über Deals (im oberen Menü) fahren, ein Fenster mit Deals angezeigt, das jedoch zu Beginn nicht angezeigt wurde. Es ist im HTML, aber es ist nicht sichtbar.

Wie kann ich bei einem DOM-Element überprüfen, ob es sichtbar ist oder nicht? Ich habe es versucht:

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

aber es scheint nicht zu funktionieren. Ich frage mich, welche Attribute ich überprüfen soll. Es kommt mir in den Sinn:

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

Irgendwelche anderen, die ich vermissen könnte?

Hommer Smith
quelle
1
Das verwendet keine Anzeige, sondern die Sichtbarkeit. Überprüfen Sie daher die Sichtbarkeit (versteckt oder sichtbar). Beispiel:document.getElementById('snDealsPanel').style.visibility
PSL
PSL. Wenn ich dies allgemeiner machen möchte, welche Attribute sollte ich überprüfen: Sichtbarkeit, Anzeige ...?
Hommer Smith
Sie können es auf Ihre eigene Weise generisch machen, aber ich sage, es verwendet Sichtbarkeit, um das Element zu überprüfen.
PSL
Hier ist mein Code (keine Abfrage) für diese Frage stackoverflow.com/a/22969337/2274995
Aleko
Der Link ist defekt, was Ihre Frage nicht leicht verständlich macht. Bitte rahmen Sie es neu ein.
Yogihosting

Antworten:

617

Gemäß dieser MDN-Dokumentation wird die offsetParentEigenschaft eines Elements zurückgegeben, nullwenn es oder eines seiner übergeordneten Elemente über die Anzeigestileigenschaft ausgeblendet wird. Stellen Sie einfach sicher, dass das Element nicht repariert ist. Ein Skript, um dies zu überprüfen, wenn Sie keine position: fixed;Elemente auf Ihrer Seite haben, könnte folgendermaßen aussehen:

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

Wenn Sie jedoch positionsfeste Elemente haben, die bei dieser Suche möglicherweise hängen bleiben, müssen Sie diese leider (und langsam) verwenden window.getComputedStyle(). Die Funktion in diesem Fall könnte sein:

// 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 ist wahrscheinlich etwas unkomplizierter, da sie mehr Randfälle berücksichtigt, aber ich wette, sie ist auch viel langsamer. Wenn Sie diesen Vorgang also viele Male wiederholen müssen, vermeiden Sie ihn am besten.

AlexZ
quelle
Wow kein Scherz. Imo sollte es keinen Grund geben, die zweite Methode als universelle Lösung zu verwenden; Keine Seite sollte feste Elemente haben, die dem Ersteller nicht explizit bekannt sind, und Sie können diese einfach manuell mit der Methode getComputedStyle () überprüfen, nachdem Sie zuerst die Methode offsetParent für alle Elemente ausgeführt haben.
AlexZ
6
Auch FYI hat gerade festgestellt, dass el.offsetParentIE9 für nicht feste Elemente nicht funktioniert. Zumindest scheint es so. (OK für IE11.) Also ging es doch mit getComputedStyle.
Nick
1
@AlexZ Ich bin mir nicht sicher, ob offsetParent in den heutigen Browsern wirklich einen Reflow ausführt, aber ja, vor ein paar Jahren haben sie das früher getan, das verstehe ich aus Berichten. Beachten Sie, dass der jsPerf nur die Ausführungsgeschwindigkeit erwähnt, während sich der Reflow auf die Anzeige bezieht. Und Reflows machen die Benutzeroberfläche schlecht. Ich persönlich werde mich nicht für die Geschwindigkeit einer Routine entscheiden, die wahrscheinlich 5/6 Mal auf einer Seite aufgerufen wird.
Ethan
2
Ach! getComputedStylefunktioniert nicht richtig: plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview Aber auch offsetParent- vielleicht sollte eine Kombination aus beiden verwendet werden?
Kerl Mograbi
2
für ie9 + ie10 können Sie überprüfen, ob offsetParent = body für nicht sichtbare Elemente ist.
SuperUberDuper
99

Alle anderen Lösungen waren für mich in einer bestimmten Situation kaputt.

Die Gewinnerantwort lautet:

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

Schließlich entschied ich, dass die beste Lösung war $(elem).is(':visible')- dies ist jedoch kein reines Javascript. es ist jquery ..

Also schaute ich auf ihre Quelle und fand, was ich wollte

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

Dies ist die Quelle: https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js

Kerl Mograbi
quelle
11
Dies wird truefür ein Element mitvisibility:hidden
Yuval A.
9
@ YuvalA.: Ja, weil das Element noch sichtbar ist. Wenn Sie ein Element so visibility:hiddeneinstellen, dass kein Inhalt mehr angezeigt wird, werden dennoch die Breite und Höhe des Elements berücksichtigt!
Jacob van Lingen
4
@Michael Sie können den jQuery-Code einfach durchsuchen und wenn Sie eine moderne IDE verwenden (versuchen Sie es, wenn nicht), können Sie mit jQuery oder einer anderen Bibliothek zu korrekten Codeteilen springen. Sie können viel lernen, während Sie Codebasen von Open Source-Projekten durchsuchen.
Lukas Liesis
53

Wenn Sie daran interessiert sind, für den Benutzer sichtbar zu sein:

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

Getestet am (unter Verwendung der Mokka- Terminologie):

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
quelle
Ein Kantenfall, wenn sich das Element außerhalb des Ansichtsfensters befindet, kann durch "if (! pointContainer) return false" abgefangen werden. Überprüfung des ersten PunktesContainer
Jerry Deng
Wenn Sie überprüfen möchten, ob der Benutzer es möglicherweise sehen könnte, müssten Sie ein scrollIntoViewRecht verwenden?! Das ist ziemlich teuer. Gibt es einen anderen klugen Weg?
Kim Kern
36

Dies kann helfen: Blenden Sie das Element aus, indem Sie es ganz links positionieren und dann die Eigenschaft offsetLeft überprüfen. Wenn Sie jQuery verwenden möchten, können Sie einfach Folgendes überprüfen : sichtbar Selektor und den Sichtbarkeitsstatus des Elements abrufen.

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
quelle
12
Das OP fordert eine no-jQuery-Antwort an.
Stephen Quan
Es wurde später bearbeitet, denke ich. Als ich antwortete, wurde es im Thread nicht erwähnt.
Md. Ashaduzzaman
2
@StephenQuan, ich habe die Antwort sowohl mit jQuery als auch mit JavaScript-Lösung aktualisiert.
Md. Ashaduzzaman
6
Sollte die Warnung für das jQuery-Beispiel nicht "Div ist sichtbar" anzeigen?
Andrei Bazanov
Ich möchte nicht schließen, dass ein Element vollständig ausgeblendet ist, nur weil sein offsetLeft kleiner als 0 ist: Was ist, wenn es nur eine kleine Anzahl von Pixeln kleiner als 0 ist und sein rechter Teil sichtbar ist? (Ich bin damit einverstanden, dass dies wie ein albernes Design erscheint, aber bei Webdesignern weiß man es heutzutage nie.) Es ist wahrscheinlich besser, die Breite zu offsetLeft hinzuzufügen und zu prüfen, ob das Ergebnis immer noch kleiner als 0 ist. Nur für den Fall.
Silas S. Brown
31

Verwenden Sie denselben Code wie jQuery:

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

Also, in einer Funktion:

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

Funktioniert wie ein Zauber in meinem Win / IE10, Linux / Firefox.45, Linux / Chrome.52 ...

Vielen Dank an jQuery ohne jQuery!

Yvan
quelle
Schön, deckt aber keine Elemente ab, die durch Überlauf verborgen werden.
Alph.Dev
schön aber was warum !! (doppelte Verneinung)?
Sunil Garg
3
Das Ergebnis als boolesch erzwingen. Da e.offsetWidthes sich um eine Ganzzahl handelt, !e.offsetWidthwird zurückgegeben, falsewenn sie e.offsetWidthhöher als Null ist (Element ist sichtbar). Wenn Sie also ein weiteres !wie in hinzufügen, !!e.offsetWidthwird zurückgegeben, truewenn e.offsetWidthes höher als Null ist. Es ist eine Abkürzung für return e.offsetWidth > 0 ? true : falseoder offensichtlich return e.offsetWidth > 0.
Yvan
16

Kombinieren Sie ein paar Antworten oben:

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

Wie AlexZ sagte, kann dies langsamer sein als einige Ihrer anderen Optionen, wenn Sie genauer wissen, wonach Sie suchen, aber dies sollte alle wichtigen Arten erfassen, wie Elemente versteckt werden.

Es kommt aber auch darauf an, was für Sie als sichtbar gilt. Beispielsweise kann die Höhe eines Divs auf 0 Pixel eingestellt werden, der Inhalt bleibt jedoch abhängig von den Überlaufeigenschaften weiterhin sichtbar. Oder der Inhalt eines Divs kann dieselbe Farbe wie der Hintergrund haben, sodass er für Benutzer nicht sichtbar ist, aber dennoch auf der Seite gerendert wird. Oder ein Div könnte vom Bildschirm verschoben oder hinter anderen Divs versteckt werden, oder sein Inhalt könnte nicht sichtbar sein, aber der Rand bleibt sichtbar. Bis zu einem gewissen Grad ist "sichtbar" ein subjektiver Begriff.

Matthew
quelle
1
Schön, aber style.opacity, style.height und style.width geben einen String zurück, damit er nicht funktioniert! ==
Maslow
Eine andere Möglichkeit, ein Element über den Stil auszublenden, besteht darin, dass seine Farbe mit der Hintergrundfarbe übereinstimmt oder der Z-Index niedriger ist als bei anderen Elementen.
Nu Everest
Das hinzuzufügen display:nonewäre großartig. Eine richtige Arbeitslösung!
Gijo Varghese
7

Ich habe eine leistungsfähigere Lösung als die getComputedStyle () -Lösung von AlexZ, wenn man positionierte Elemente hat, wenn man bereit ist, einige Randfälle zu ignorieren (Kommentare überprüfen):

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

Randnotiz: Genau genommen muss zuerst "Sichtbarkeit" definiert werden. In meinem Fall betrachte ich ein Element als sichtbar, solange ich alle DOM-Methoden / -Eigenschaften problemlos ausführen kann (auch wenn die Deckkraft 0 ist oder die CSS-Sichtbarkeitseigenschaft "ausgeblendet" ist usw.).

Munawwar
quelle
6

Wenn das Element regelmäßig sichtbar ist (Anzeige: Block und Sichtbarkeit: sichtbar), aber ein übergeordneter Container ausgeblendet ist, können wir clientWidth und clientHeight verwenden, um dies zu überprüfen.

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

Plunker (hier klicken)

Vlada
quelle
ele.style.visibility !== 'hidden'ist hier überflüssig. In diesem Fall sind clientWidth und clientHeight 0.
subdavis
5

Wenn wir nur grundlegende Methoden zum Erkennen der Sichtbarkeit sammeln, darf ich nicht vergessen:

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

Und wie man Attribute erhält:

element.getAttribute(attributename);

Also, in Ihrem Beispiel:

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

Aber was? Hier funktioniert es nicht. Wenn Sie genauer hinschauen, werden Sie feststellen, dass die Sichtbarkeit nicht als Attribut für das Element aktualisiert wird, sondern mithilfe der styleEigenschaft. Dies ist eines von vielen Problemen beim Versuch, das zu tun, was Sie tun. Unter anderem: Sie können nicht garantieren, dass in einem Element tatsächlich etwas zu sehen ist, nur weil Sichtbarkeit, Anzeige und Deckkraft die richtigen Werte haben. Möglicherweise fehlt es immer noch an Inhalt oder an Höhe und Breite. Ein anderes Objekt könnte es verdecken. Für weitere Details enthüllt eine schnelle Google - Suche diese und schließt sogar eine Bibliothek , um zu versuchen , das Problem zu lösen. (YMMV)

Schauen Sie sich die folgenden möglichen Duplikate dieser Frage mit hervorragenden Antworten an, einschließlich einiger Erkenntnisse des mächtigen John Resig. Ihr spezifischer Anwendungsfall unterscheidet sich jedoch geringfügig vom Standard, daher verzichte ich auf das Markieren:

(BEARBEITEN: OP SAGT, ER SCHRITKT SEITEN, ERSTELLT SIE NICHT, SO IST UNTEN NICHT ANWENDBAR) Eine bessere Option? Binden Sie die Sichtbarkeit von Elementen an Modelleigenschaften und machen Sie die Sichtbarkeit immer von diesem Modell abhängig, ähnlich wie Angular es mit ng-show tut. Sie können dies mit jedem gewünschten Werkzeug tun: Angular, Plain JS, was auch immer. Besser noch, Sie können die DOM-Implementierung im Laufe der Zeit ändern, aber Sie können immer den Status aus dem Modell anstelle des DOM lesen. Deine Wahrheit aus dem DOM zu lesen ist schlecht. Und langsam. Es ist viel besser, das Modell zu überprüfen und auf Ihre Implementierung zu vertrauen, um sicherzustellen, dass der DOM-Status das Modell widerspiegelt. (Und verwenden Sie automatisierte Tests, um diese Annahme zu bestätigen.)

XML
quelle
Ich analysiere Websites, dies ist nicht für meine eigene Website ... :)
Hommer Smith
4

Die akzeptierte Antwort hat bei mir nicht funktioniert. Antwort für das Jahr 2020 :

1) Die Methode (elem.offsetParent! == null) funktioniert in Firefox einwandfrei , in Chrome jedoch nicht. Für Chrome "Position: fest;" OffsetParent gibt auch "null" zurück, selbst wenn das Element auf der Seite sichtbar ist.

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>

Sie können diesen Megatest https://stackoverflow.com/a/11639664/4481831 sehen (führen Sie ihn mit mehreren Browsern aus, um die Unterschiede zu erkennen).

2) Die (getComputedStyle (elem) .display! == 'none') funktioniert nicht, da das Element unsichtbar sein kann, da eine der übergeordneten Anzeigeeigenschaften auf none gesetzt ist. GetComputedStyle fängt dies nicht ab.

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) Die (elem.clientHeight! == 0) . Diese Methode wird nicht durch die festgelegte Position beeinflusst und prüft auch, ob die übergeordneten Elemente nicht sichtbar sind. Es gibt jedoch Probleme mit einfachen Elementen, die kein CSS-Layout haben. Weitere Informationen finden Sie hier

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) Die (elem.getClientRects (). Length! == 0) , die die Probleme der vorherigen 3 Methoden zu übertreffen scheinen. Es gibt jedoch Probleme mit Elementen, die CSS-Tricks (außer "display: none") verwenden, um sich auf der Seite auszublenden.

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>

SCHLUSSFOLGERUNG: Ich habe Ihnen also gezeigt, dass keine Methode perfekt ist. Um eine ordnungsgemäße Sichtbarkeitsprüfung durchzuführen, müssen Sie eine Kombination der letzten drei Methoden verwenden.

crisc82
quelle
3

Nur als Referenz sollte angemerkt werden, dass getBoundingClientRect()in bestimmten Fällen funktionieren kann.

Eine einfache Überprüfung, ob das Element mithilfe von versteckt ist, display: nonekönnte beispielsweise folgendermaßen aussehen:

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

Dies ist auch praktisch, da es auch die Breite Null, die Höhe Null und position: fixedFälle abdeckt . Es werden jedoch keine Elemente gemeldet, die mit opacity: 0oder verborgen sind visibility: hidden(aber auch nicht offsetParent).

verkörpern
quelle
Beste Antwort für mich ... einfach und effektiv. Und keine einzige Gegenstimme nach 3 Jahren! Zeigt weiter den Wert von „Crowd Wisdom“. Meine Version : var isVisible = el => (r => r.width && r.height)(el.getBoundingClientRect());. Dann kann ich Arrays von Elementen folgendermaßen filtern : $$(sel).filter(isVisible).
7vujy0f0hy
Ich finde es die einfachste Lösung developer.mozilla.org/en-US/docs/Web/API/Element/…
Marian07
Dies funktioniert nicht, wenn es für den Benutzer sichtbar ist. Wenn Sie
Ray Foss
3

Was ich also gefunden habe, ist die praktikabelste Methode:

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

Dies baut auf diesen Tatsachen auf:

  • Ein display: noneElement (auch ein verschachteltes) hat weder eine Breite noch eine Höhe.
  • visiblityist hiddensogar für verschachtelte Elemente.

Sie müssen also nicht offsetParentim DOM-Baum testen oder eine Schleife erstellen, um zu testen, welche übergeordneten Elemente vorhanden sind visibility: hidden. Dies sollte auch in IE 9 funktionieren.

Sie könnten argumentieren, ob opacity: 0und reduzierte Elemente (hat eine Breite, aber keine Höhe - oder umgekehrt) auch nicht wirklich sichtbar sind. Aber andererseits sind sie nicht per se versteckt.

Tokimon
quelle
3

Eine kleine Ergänzung zu Ohad Navons Antwort.

Wenn die Mitte des Elements zu einem anderen Element gehört, werden wir es nicht finden.

Stellen Sie also sicher, dass einer der Punkte des Elements sichtbar ist

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

Die obige Antwort von @Guy Messika zu verbessern , falsch zu brechen und zurückzugeben, wenn der Mittelpunkt 'X <0 ist, ist falsch, da das Element auf der rechten Seite möglicherweise in die Ansicht aufgenommen wird. Hier ist eine Lösung:

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;
}
Israel
quelle
2

Der jQuery-Code von http://code.jquery.com/jquery-1.11.1.js hat einen isHidden-Parameter

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

Es sieht also so aus, als ob es eine zusätzliche Prüfung für das Eigentümerdokument gibt

Ich frage mich, ob dies wirklich die folgenden Fälle erfasst:

  1. Elemente, die hinter anderen Elementen basierend auf zIndex versteckt sind
  2. Elemente mit voller Transparenz machen sie unsichtbar
  3. Elemente außerhalb des Bildschirms positioniert (dh links: -1000px)
  4. Elemente mit Sichtbarkeit: versteckt
  5. Elemente mit Anzeige: keine
  6. Elemente ohne sichtbaren Text oder Unterelemente
  7. Elemente mit Höhe oder Breite auf 0 gesetzt
Scott Izu
quelle
0

Hier ist der Code, den ich geschrieben habe, um das einzig sichtbare unter einigen ähnlichen Elementen zu finden und den Wert seines Attributs "class" ohne jQuery zurückzugeben:

  // 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");
    }
  }
unbestimmt
quelle
0

Das habe ich getan:

HTML & CSS: Das Element wurde standardmäßig ausgeblendet

<html>
<body>

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

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

</body>
</html> 

JavaScript: Es wurde ein Code hinzugefügt, um zu überprüfen, ob die Sichtbarkeit ausgeblendet ist oder nicht:

<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
quelle
-1

Dies ist eine Möglichkeit, dies für alle CSS-Eigenschaften einschließlich der Sichtbarkeit zu bestimmen:

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

Es funktioniert für jede CSS-Eigenschaft und ist sehr vielseitig und zuverlässig.

William Green
quelle