it-swarm.com.de

Prüfen Sie, ob das Element in DOM sichtbar ist

Gibt es eine Möglichkeit, zu überprüfen, ob ein Element in Pure JS sichtbar ist (keine jQuery)?

Auf dieser Seite zum Beispiel: Performance Bikes Wenn Sie den Mauszeiger über Angebote bewegen (im oberen Menü), wird ein Fenster mit Angeboten angezeigt, das zu Beginn jedoch nicht angezeigt wurde. Es befindet sich im HTML-Code, ist aber nicht sichtbar.

Wie kann ich also bei einem DOM-Element prü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 prüfen sollte. Es fällt mir ein:

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

Gibt es noch andere, die mir fehlen könnten?

254
Hommer Smith

Gemäß dieser MDN-Dokumentation gibt die offsetParent -Eigenschaft eines Elements null zurück, wenn das Element oder eines seiner übergeordneten Elemente über die Anzeigestileigenschaft ausgeblendet wird. Stellen Sie nur sicher, dass das Element nicht fixiert ist. Ein Skript, das dies überprüft, 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)
}

Auf der anderen Seite, wenn Sie do über fixe Elemente verfügen, die bei dieser Suche eingeklemmt werden könnten, müssen Sie leider (und langsam) window.getComputedStyle() verwenden. Die Funktion könnte in diesem Fall lauten:

// 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 hier mehr Edge-Fälle berücksichtigt werden, aber ich wette, es ist auch viel langsamer. Wenn Sie also diese Operation viele Male wiederholen müssen, vermeiden Sie es am besten.

436
AlexZ

Alle anderen Lösungen brachen für einige Situationen für mich .. 

Sehen Sie die erfolgreiche Antwort bei: 

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

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

also habe ich auf ihre Quelle geschaut und gefunden, 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

84
guy mograbi

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 (mit Mocha 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;
    });
});
33
Ohad Navon

Dies kann hilfreich sein: Blenden Sie das Element aus, indem Sie es ganz nach links positionieren, und überprüfen Sie die Eigenschaft offsetLeft. Wenn Sie jQuery verwenden möchten, können Sie einfach den Selektor : visible überprüfen 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 hidden!!");        
}

jsFiddle

30
Ashad Shanto

Verwenden Sie den gleichen 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!

21
Yvan

Einige Antworten oben kombinieren:

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 gesagt hat, kann dies langsamer sein als einige Ihrer anderen Optionen, wenn Sie genauer wissen, wonach Sie suchen. Dies sollte jedoch die Hauptversteckmöglichkeiten der Elemente berücksichtigen. 

Es kommt aber auch darauf an, was für Sie als sichtbar gilt. Beispielsweise kann die Höhe eines Div auf 0px gesetzt werden, der Inhalt bleibt jedoch abhängig von den Überlaufeigenschaften sichtbar. Oder der Inhalt eines Divs könnte dieselbe Farbe wie der Hintergrund haben, sodass er für Benutzer nicht sichtbar ist, aber auf der Seite angezeigt wird. Oder ein Div kann aus dem Bildschirm verschoben oder hinter anderen Divs ausgeblendet werden, oder sein Inhalt ist möglicherweise nicht sichtbar, aber der Rand bleibt sichtbar. "Sichtbar" ist gewissermaßen ein subjektiver Begriff.

8
Matthew

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

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

Plunker (hier klicken)

6
Vlada

Ich habe eine leistungsfähigere Lösung im Vergleich zu AlexZs getComputedStyle () - Lösung , wenn man fixierte Elemente der Position hat, wenn man bereit ist, einige Edge-Fälle zu ignorieren (siehe Kommentare):

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

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

6
Munawwar

Wenn wir nur grundlegende Möglichkeiten zur Erkennung 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 deinem Beispiel:

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

Aber was? Hier geht es nicht. Wenn Sie genauer hinschauen, werden Sie feststellen, dass die Sichtbarkeit nicht als Attribut für das Element, sondern mithilfe der style-Eigenschaft aktualisiert wird. 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 alle die richtigen Werte haben. Möglicherweise fehlt es an Inhalt oder an Höhe und Breite. Ein anderes Objekt könnte es verdecken. Für weitere Details wird in einer schnellen Google-Suche this angezeigt, und es enthält sogar eine Bibliothek, um das Problem zu lösen. (YMMV)

Schauen Sie sich das Folgende an, welche mögliche Duplikate dieser Frage sind, mit exzellenten Antworten, einschließlich einiger Einsichten des mächtigen John Resig. Ihr spezifischer Anwendungsfall unterscheidet sich jedoch geringfügig von dem Standard, so dass ich das Markieren unterlasse:

(BEARBEITEN: OP SAGT, DASS ER SCRAPING-SEITEN, NICHT ERSTELLEN, SO UNTEN IST NICHT ANWENDBAR). Binden Sie die Sichtbarkeit von Elementen an die Modelleigenschaften, und machen Sie die Sichtbarkeit immer von diesem Modell abhängig, wie es Angular mit ng-show tut. Sie können dies mit jedem beliebigen Werkzeug tun: Angular, plain JS oder was auch immer. Besser noch, Sie können die DOM-Implementierung im Laufe der Zeit ändern, Sie können jedoch immer den Status aus dem Modell anstelle des DOMs lesen. Das Lesen Ihrer Wahrheit aus dem DOM 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.) 

5
XML

Was ich 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 Fakten auf:

  • Ein display: none-Element (auch ein verschachteltes) Element hat weder Breite noch Höhe.
  • visiblity ist hidden auch für verschachtelte Elemente.

Es ist also nicht nötig, offsetParent zu testen oder in der DOM-Baumstruktur eine Schleife zu machen, um zu testen, welcher Elternteil visibility: hidden hat. Dies sollte auch in IE 9 funktionieren.

Sie könnten argumentieren, ob opacity: 0 und ausgeblendete Elemente (Breite, aber keine Höhe - oder umgekehrt) nicht wirklich sichtbar sind. Aber sie sind auch nicht sozusagen versteckt.

3
Tokimon

Nur für die Referenz sollte beachtet werden, dass getBoundingClientRect() in bestimmten Fällen funktionieren kann.

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

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

Dies ist auch praktisch, weil es auch Fälle mit der Breite Null, der Höhe Null und dem Code position: fixed abdeckt. Elemente, die mit opacity: 0 oder visibility: hidden ausgeblendet sind, dürfen jedoch nicht gemeldet werden (dies gilt jedoch auch für offsetParent).

2
incarnate

Der jQuery-Code aus 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 );
};

Anscheinend gibt es eine zusätzliche Prüfung, die sich auf das Besitzerdokument bezieht

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

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

Ein kleiner Zusatz zur Antwort von ohad navon.

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

So stellen Sie sicher, dass einer der Punkte des Elements als sichtbar erkannt wird

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;
}
2
Guy Messika

Dies gibt nur dann true zurück, wenn das Element und alle seine Vorfahren sichtbar sind. Es werden nur die Eigenschaften display und visibilitystyle betrachtet:

    var isVisible = function(el){
        // returns true iff el and all its ancestors are visible
        return el.style.display !== 'none' && el.style.visibility !== 'hidden'
        && (el.parentElement? isVisible(el.parentElement): true)
    };
1
Max Heiber

Verbesserung von @Guy Messikas Antwort oben , brechen und False zurückgeben, wenn der Mittelpunkt 'X ist <0 falsch ist, da das rechte Element möglicherweise in die Ansicht geht. hier ist ein fix:

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

Dies ist ein Weg, um es für alle CSS-Eigenschaften einschließlich 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.

0
William Green

Das habe ich gemacht:

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 verborgen 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>
0
Ajas Jansher

Hier ist der Code, den ich geschrieben habe, um das einzig sichtbare unter einigen ähnlichen Elementen zu finden und den Wert seines "class" -Attributs 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");
    }
  }
0
not_specified