Sprawdź, czy element jest widoczny w DOM


377

Czy jest jakiś sposób, aby sprawdzić, czy element jest widoczny w czystym JS (bez jQuery)?

Na przykład na tej stronie: Rowery wyczynowe , jeśli najedziesz kursorem na Oferty (w górnym menu), pojawi się okno ofert, ale na początku nie zostało wyświetlone. Jest w HTML, ale nie jest widoczny.

Zatem, biorąc pod uwagę element DOM, jak mogę sprawdzić, czy jest widoczny, czy nie? Próbowałem:

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

ale wydaje się, że nie działa. Zastanawiam się, które atrybuty powinienem sprawdzić. Przychodzi mi na myśl:

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

Jakieś inne, za którymi mogę tęsknić?


1
To nie korzysta z wyświetlania, wykorzystuje widoczność, więc sprawdź widoczność (ukrytą lub widoczną). np .:document.getElementById('snDealsPanel').style.visibility
PSL,

PSL. Jeśli chciałbym to zrobić bardziej ogólnie, które atrybuty powinienem sprawdzić: widoczność, wyświetlanie ...?
Hommer Smith

Możesz zrobić to na swój sposób, ale mówię o tym, że sprawdza widoczność elementu.
PSL,

Oto mój kod (bez jquery) dla tego pytania stackoverflow.com/a/22969337/2274995
Aleko

Link jest zepsuty, co sprawia, że ​​twoje pytanie nie jest łatwe do zrozumienia. Uprzejmie go ponownie wykadruj.
yogihosting

Odpowiedzi:


617

Zgodnie z tą dokumentacją MDNoffsetParent właściwość elementu zwróci się nullza każdym razem, gdy on lub którykolwiek z jego rodziców zostanie ukryty za pośrednictwem właściwości stylu wyświetlania. Upewnij się tylko, że element nie jest naprawiony. Skrypt do sprawdzenia tego, jeśli nie masz żadnych position: fixed;elementów na stronie, może wyglądać następująco:

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

Z drugiej strony, jeśli nie mają pozycji stałych elementów, które mogą się złapać w tej kategorii, będzie niestety (i powoli) mają do użytku window.getComputedStyle(). W takim przypadku funkcją może być:

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

Opcja nr 2 jest prawdopodobnie nieco prostsza, ponieważ uwzględnia więcej przypadków przewagi, ale założę się, że jest również znacznie wolniejsza, więc jeśli musisz powtarzać tę operację wiele razy, najlepiej tego uniknąć.


Wow, bez żartów. Imo nie powinno być powodu, aby używać drugiej metody jako uniwersalnego rozwiązania; żadna strona nie powinna mieć ustalonych elementów, których twórca nie jest wyraźnie świadomy, i można je po prostu sprawdzić ręcznie za pomocą metody getComputedStyle () po uruchomieniu najpierw metody offsetParent na wszystkich elementach.
AlexZ

6
Również FYI, właśnie odkryłem, że el.offsetParentnie działa na IE9 dla nie naprawionych elementów. A przynajmniej tak się wydaje. (OK dla IE11.) Tak więc poszło w getComputedStylekońcu.
Nick

1
@AlexZ Nie jestem pewien, czy offsetParent naprawdę robi reflow w dzisiejszych przeglądarkach, ale tak, kilka lat temu, kiedyś, to rozumiem z raportów. Zauważ, że jsPerf wspomina tylko o szybkości wykonania, podczas gdy reflow dotyczy wyświetlania. Reflow powoduje, że interfejs użytkownika jest słaby. Osobiście nie wybiorę szybkości dla procedury, która prawdopodobnie nazywa się 5/6 razy na stronie.
Ethan

2
Niestety! getComputedStylenie działa poprawnie: plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview Jednak tak też jest offsetParent- być może należy zastosować kombinację tych dwóch?
guy mograbi

2
dla ie9 + ie10 możesz sprawdzić, czy offsetParent = body dla niewidocznych elementów.
SuperUberDuper,

99

Dla mnie wszystkie inne rozwiązania się zepsuły.

Zobacz zwycięską odpowiedź w podziale na:

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

W końcu zdecydowałem, że najlepszym rozwiązaniem jest $(elem).is(':visible')- jednak nie jest to czysty JavaScript. to jquery ..

więc zerknąłem na ich źródło i znalazłem to, czego chciałem

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

To jest źródło: https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js


11
W ten sposób powrót truedo elementu ovisibility:hidden
Yuval A.

9
@YuvalA .: Tak, ponieważ element jest nadal widoczny. Ustawienie elementu tak, aby visibility:hiddennie wyświetlał już żadnej zawartości, ale nadal przyjmuje szerokość i wysokość elementu!
Jacob van Lingen,

4
@Michael możesz łatwo przeglądać kod jQuery, a jeśli używasz dowolnego nowoczesnego IDE (spróbuj, jeśli nie), możesz przejść do poprawiania części kodu podczas korzystania z jQuery lub dowolnej innej biblioteki lib. Możesz się wiele nauczyć podczas przeglądania baz kodów projektów open source.
Lukas Liesis

53

Jeśli jesteś zainteresowany tym, co widzi użytkownik:

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

Testowane na (przy użyciu terminologii mokka ):

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

przypadek krawędzi, jeśli element jest umieszczony poza rzutnią, może zostać przechwycony przez „if (! pointContainer) return false;” sprawdzanie pierwszego punktu Kontener
Jerry Deng

Jeśli chcesz sprawdzić, czy użytkownik może to zobaczyć, musisz użyć scrollIntoViewprawa ?! To jest dość drogie. Czy istnieje inny sprytny sposób?
Kim Kern

36

Może to pomóc: Ukryć element, ustawiając go na skrajnie lewej pozycji, a następnie sprawdzając właściwość offsetLeft. Jeśli chcesz użyć jQuery, możesz po prostu sprawdzić : widoczny selektor i uzyskać stan widoczności elementu.

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
OP żąda odpowiedzi typu no-jQuery.
Stephen Quan

To chyba edytowane później. Kiedy odpowiedziałem, w wątku nie było o tym mowy.
Md. Ashaduzzaman

2
@StephenQuan, zaktualizowałem odpowiedź zarówno w rozwiązaniu jQuery, jak i javaScript.
Md. Ashaduzzaman

6
w przykładzie jQuery nie powinien ostrzegać: „Div jest widoczny?”
Andrei Bazanov,

Nie chciałbym wyciągać wniosku, że element jest całkowicie ukryty tylko dlatego, że jego offsetLeft jest mniejszy niż 0: co jeśli jest tylko niewielką liczbą pikseli mniejszą niż 0 i jego prawa część jest widoczna? (Zgadzam się, że wyglądałoby to na głupiutki projekt, ale w dzisiejszych czasach nigdy nie wiadomo projektantom stron). Prawdopodobnie lepiej jest dodać szerokość do offsetLeft i sprawdzić, czy wynik jest nadal mniejszy niż 0. Na wszelki wypadek.
Silas S. Brown

31

Użyj tego samego kodu, co robi jQuery:

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

Tak więc w funkcji:

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

Działa jak urok w moim Win / IE10, Linux / Firefox.45, Linux / Chrome.52 ...

Wielkie podziękowania dla jQuery bez jQuery!


Ładne, ale nie obejmuje elementów ukrywanych przez przelew.
Alph.Dev,

fajnie, ale co dlaczego !! (podwójna negacja)?
Sunil Garg,

3
Aby wymusić wynik jako wartość logiczną. Ponieważ e.offsetWidthjest liczbą całkowitą, !e.offsetWidthzwróci, falsejeśli e.offsetWidthjest wyższa od zera (element jest widoczny). Tak więc dodanie kolejnego !jak w !!e.offsetWidthzwróci, truejeśli e.offsetWidthjest większe od zera. Jest to skrót od return e.offsetWidth > 0 ? true : falselub oczywiście return e.offsetWidth > 0.
Yvan

16

Łącząc kilka odpowiedzi powyżej:

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

Jak powiedział AlexZ, może to być wolniejsze niż niektóre inne opcje, jeśli wiesz bardziej dokładnie, czego szukasz, ale to powinno uchwycić wszystkie główne sposoby ukrywania elementów.

Ale zależy to również od tego, co dla Ciebie jest widoczne. Na przykład wysokość div może być ustawiona na 0 pikseli, ale zawartość jest nadal widoczna w zależności od właściwości przepełnienia. Lub zawartość div może być w tym samym kolorze co tło, aby nie była widoczna dla użytkowników, ale nadal renderowana na stronie. Lub element div może zostać przeniesiony poza ekran lub ukryty za innymi elementami div lub jego zawartość może być niewidoczna, ale ramka nadal widoczna. Do pewnego stopnia „widoczny” jest pojęciem subiektywnym.


1
Ładne, ale style.opacity, style.height i style.width zwracają ciąg znaków, aby nie działał! ==
Maslow

Innym sposobem, w jaki element może być ukryty za pomocą stylu, jest to, że jego kolor może pasować do koloru tła lub jego indeks Z może być niższy niż w przypadku innych elementów.
nve everest

dodanie display:nonedo tego byłoby świetne. Właściwe działające rozwiązanie!
Gijo Varghese,

7

Mam bardziej wydajne rozwiązanie w porównaniu do rozwiązania getComputedStyle () AlexZ, gdy ktoś ma elementy „ustalone” pozycji, jeśli chce zignorować niektóre przypadki krawędzi (sprawdź komentarze):

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

Uwaga dodatkowa: Ściśle mówiąc, „widoczność” musi zostać zdefiniowana w pierwszej kolejności. W moim przypadku rozważam element widoczny, o ile mogę bez problemu uruchomić na nim wszystkie metody / właściwości DOM (nawet jeśli krycie wynosi 0 lub właściwość widoczności CSS jest „ukryta” itp.).


6

Jeśli element jest regularnie widoczny (display: block and visibillity: visible), ale jakiś kontener nadrzędny jest ukryty, możemy to sprawdzić za pomocą clientWidth i clientHeight .

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

Plunker (kliknij tutaj)


ele.style.visibility !== 'hidden'jest tutaj zbędny. W takim przypadku clientWidth i clientHeight będą wynosić 0.
subdavis

5

Jeśli tylko zbieramy podstawowe sposoby wykrywania widoczności, nie zapomnę:

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

A jak uzyskać atrybuty:

element.getAttribute(attributename);

W twoim przykładzie:

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

Ale co? Tu nie działa. Przyjrzyj się bliżej, a zobaczysz, że widoczność jest aktualizowana nie jako atrybut elementu, ale za pomocą stylewłaściwości. Jest to jeden z wielu problemów z próbami robienia tego, co robisz. Między innymi: nie możesz zagwarantować, że w elemencie jest coś do zobaczenia, tylko dlatego, że jego widoczność, wyświetlanie i krycie mają prawidłowe wartości. Wciąż może brakować treści lub może mieć wysokość i szerokość. Inny obiekt może to zasłonić. Aby uzyskać więcej informacji, szybkie wyszukiwanie Google ujawnia to , a nawet zawiera bibliotekę, aby spróbować rozwiązać problem. (YMMV)

Sprawdź poniższe, które są możliwymi duplikatami tego pytania, z doskonałymi odpowiedziami, w tym wglądem potężnego Johna Resiga. Jednak konkretny przypadek użycia różni się nieco od standardowego, więc powstrzymam się od oznaczania:

(EDYCJA: OP MÓWI, ŻE STRONY ZŁOMU, NIE TWORZYCIE SIĘ, A PONIŻEJ NIE MA ZASTOSOWANIA) Lepsza opcja? Powiąż widoczność elementów z właściwościami modelu i zawsze uzależnij widoczność od tego modelu, podobnie jak Angular z ng-show. Możesz to zrobić za pomocą dowolnego narzędzia: kątowego, zwykłego JS, cokolwiek. Co więcej, możesz zmieniać implementację DOM w miarę upływu czasu, ale zawsze będziesz w stanie odczytać stan z modelu zamiast DOM. Czytanie swojej prawdy z DOM jest złe. I powoli. Znacznie lepiej sprawdzić model i zaufać implementacji, aby upewnić się, że stan DOM odzwierciedla model. (I użyj automatycznych testów, aby potwierdzić to założenie).



4

Przyjęta odpowiedź nie działała dla mnie. Odpowiedź na rok 2020 :

1) Metoda (elem.offsetParent! == null) działa poprawnie w przeglądarce Firefox, ale nie w przeglądarce Chrome. W przypadku Chrome „pozycja: stała;” spowoduje również, że offsetParent zwróci „null” nawet element, jeśli jest widoczny na stronie.

Próbny:

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

możesz zobaczyć tego największego faceta https://stackoverflow.com/a/11639664/4481831 (uruchom go z wieloma przeglądarkami, aby zobaczyć różnice).

2) Funkcja (getComputedStyle (elem) .display! == 'none') nie działa, ponieważ element może być niewidoczny, ponieważ jedna z właściwości display rodzica jest ustawiona na none, getComputedStyle tego nie złapie.

Próbny:

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) (elem.clientHeight! == 0) . Ta metoda nie ma wpływu na ustaloną pozycję, a także sprawdza, czy rodzice elementów nie są widoczni. Ale ma problemy z prostymi elementami, które nie mają układu css, zobacz więcej tutaj

Próbny:

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) (elem.getClientRects (). Length! == 0), które wydają się przekraczać problemy poprzednich 3 metod. Ma jednak problemy z elementami wykorzystującymi sztuczki CSS (inne niż „display: none”) do ukrywania się na stronie.

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>

WNIOSEK: Więc pokazałem wam, że żadna metoda nie jest idealna. Aby właściwie sprawdzić widoczność, musisz użyć kombinacji 3 ostatnich metod.


3

Tylko w celach informacyjnych należy zauważyć, że getBoundingClientRect()może działać w niektórych przypadkach.

Na przykład proste sprawdzenie, czy element jest ukryty, display: nonemoże wyglądać mniej więcej tak:

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

Jest to również przydatne, ponieważ obejmuje również zerową szerokość, zerową wysokość i position: fixedprzypadki. Jednak nie zgłasza elementów ukrytych za pomocą opacity: 0lub visibility: hidden(ale nie ma offsetParent).


Najlepsza odpowiedź dla mnie ... prosta i skuteczna. I żaden głos nie zyskał po 3 latach! Dalej pokazuje wartość „mądrości tłumu”. Moja wersja: var isVisible = el => (r => r.width && r.height)(el.getBoundingClientRect());. Następnie można filtrować tablice elementów w następujący sposób: $$(sel).filter(isVisible).
7vujy0f0hy

Uważam, że jest to najprostsze rozwiązanie developer.mozilla.org/en-US/docs/Web/API/Element/…
Marian07

To nie działa, gdy jest widoczne dla użytkownika .... jeśli przewiniesz, pozostanie prawdziwe
Ray Foss

3

Znalazłem więc najbardziej wykonalną metodę:

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

Opiera się to na następujących faktach:

  • display: noneElementem (również zagnieżdżonego jeden) nie ma szerokość ani wysokość.
  • visiblityjest hiddennawet dla elementów zagnieżdżonych.

Nie ma więc potrzeby testowania offsetParentani zapętlania drzewa DOM w celu sprawdzenia, który rodzic ma visibility: hidden. Powinno to działać nawet w IE 9.

Można się spierać, czy opacity: 0zwinięte elementy (ma szerokość, ale nie ma wysokości - lub odwrotnie) nie są tak naprawdę widoczne. Ale znowu nie są ukryte.


3

Mały dodatek do odpowiedzi Ohada Navona.

Jeśli środek elementu należy do innego elementu, nie znajdziemy go.

Aby upewnić się, że jeden z punktów elementu jest widoczny

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

Poprawianie powyższej odpowiedzi @Guy Messika , łamanie i zwracanie wartości false, jeśli punkt środkowy „X jest <0” jest błędny, ponieważ prawy element elementu może przejść do widoku. oto poprawka:

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

Kod jQuery z http://code.jquery.com/jquery-1.11.1.js ma parametr 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 );
};

Wygląda więc na to, że istnieje dodatkowa kontrola związana z dokumentem właściciela

Zastanawiam się, czy to naprawdę łapie następujące przypadki:

  1. Elementy ukryte za innymi elementami opartymi na zIndex
  2. Elementy z przezroczystością pełne, dzięki czemu są niewidoczne
  3. Elementy ustawione poza ekranem (tj. Po lewej: -1000px)
  4. Elementy z widocznością: ukryte
  5. Elementy z wyświetlaczem: brak
  6. Elementy bez widocznego tekstu lub podelementów
  7. Elementy o wysokości lub szerokości ustawionej na 0

0

Oto kod, który napisałem, aby znaleźć jedyny widoczny spośród kilku podobnych elementów i zwrócić wartość jego atrybutu „class” bez 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

Oto co zrobiłem:

HTML i CSS: domyślnie ukryto element

<html>
<body>

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

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

</body>
</html> 

JavaScript: Dodano kod sprawdzający, czy widoczność jest ukryta, czy nie:

<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

Jest to sposób na określenie tego dla wszystkich właściwości css, w tym widoczności:

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

Działa z każdą właściwością css i jest bardzo wszechstronny i niezawodny.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.