Verifique se o elemento está visível no DOM

378

Existe alguma maneira de verificar se um elemento é visível em JS puro (sem jQuery)?

Então, por exemplo, nesta página: Bicicletas de desempenho , se você passar o mouse sobre Ofertas (no menu superior), uma janela de ofertas aparecerá, mas no começo ela não foi exibida. Está no HTML, mas não é visível.

Portanto, dado um elemento DOM, como posso verificar se é visível ou não? Eu tentei:

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

mas não parece estar funcionando. Gostaria de saber quais atributos devo verificar. Isso vem à minha mente:

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

Algum outro que eu possa estar perdendo?

Hommer Smith
fonte
11
Como não usa exibição, usa visibilidade, portanto verifique a visibilidade (oculta ou visível). ex:document.getElementById('snDealsPanel').style.visibility
PSL
PSL. Se eu gostaria de fazer isso de maneira mais geral, quais atributos devo verificar: visibilidade, exibição ...?
Homer Smith
Você pode torná-lo genérico à sua maneira, mas o que estou dizendo é que ele usa visibilidade inspecionando o elemento.
PSL
Aqui está o meu código (sem jQuery) para esta pergunta stackoverflow.com/a/22969337/2274995
Aleko
O link está quebrado, o que torna sua pergunta não fácil de entender. Reformule-o gentilmente.
yogihosting

Respostas:

618

De acordo com esta documentação do MDN , a offsetParentpropriedade de um elemento retornará nullsempre que ele ou qualquer um de seus pais estiver oculto pela propriedade de estilo de exibição. Apenas verifique se o elemento não está fixo. Um script para verificar isso, se você não tiver position: fixed;elementos em sua página, pode se parecer com:

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

Por outro lado, se você não tem elementos de posição fixa que pode ser pego nessa busca, você vai, infelizmente (e lentamente) tem que usar window.getComputedStyle(). A função nesse caso pode ser:

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

A opção 2 é provavelmente um pouco mais direta, pois é responsável por mais casos extremos, mas aposto que é muito mais lento também; portanto, se você precisar repetir essa operação muitas vezes, é melhor evitá-la.

AlexZ
fonte
Uau, não está brincando. Imo, não deve haver razão para usar o segundo método como uma solução universal; nenhuma página deve ter elementos fixos que seu criador não conhece explicitamente, e é possível apenas checá-los manualmente usando o método getComputedStyle () depois de executar o método offsetParent em todos os elementos primeiro.
AlexZ #
6
Também para sua informação, acabei de descobrir que el.offsetParentnão estava funcionando no IE9 para elementos não fixos. Ou pelo menos parece. (OK para o IE11, no entanto) getComputedStyle.
Nick
11
@AlexZ Não tenho certeza se o offsetParent realmente reflui nos navegadores de hoje, mas sim, há alguns anos, eles costumavam fazer, é isso que eu entendo nos relatórios. Observe que o jsPerf menciona apenas a velocidade de execução, enquanto o reflow é sobre a exibição. E os refluxos tornam a interface do usuário ruim. Eu pessoalmente não irei à velocidade de uma rotina que provavelmente é chamada 5/6 vezes em uma página.
Ethan
2
infelizmente! getComputedStylenão funciona corretamente: plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview No entanto, o mesmo acontece offsetParent- talvez uma combinação dos dois deva ser usada?
cara Mograbi
2
para ie9 + ie10, você pode verificar se offsetParent = body para elementos não visíveis.
SuperUberDuper
99

Todas as outras soluções quebraram para alguma situação para mim ..

Veja a resposta vencedora em:

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

Por fim, decidi que a melhor solução era $(elem).is(':visible') - no entanto, esse não é um javascript puro. é jquery ..

então eu espiei a fonte deles e encontrei o que queria

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

Esta é a fonte: https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js

guy mograbi
fonte
11
Isso retornará truepara um elemento comvisibility:hidden
Yuval A.
9
@YuvalA .: Sim, porque o elemento ainda está visível. Definir um elemento como visibility:hiddennão mostra mais conteúdo, mas ainda ocupa a largura e a altura do elemento!
Jacob van Lingen
4
@ Michael, você pode navegar facilmente pelo código do jQuery e, se estiver usando algum IDE moderno (tente se não estiver), poderá pular para corrigir partes do código enquanto estiver usando o jQuery ou qualquer outra biblioteca. Você pode aprender muito enquanto navega em bases de código de projetos de código aberto.
Lukas Liesis
53

Se você estiver interessado em ser visível pelo usuário:

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

Testado em (usando a terminologia mocha ):

describe.only('visibility', function () {
    let div, visible, notVisible, inViewport, leftOfViewport, rightOfViewport, aboveViewport,
        belowViewport, notDisplayed, zeroOpacity, zIndex1, zIndex2;
    before(() => {
        div = document.createElement('div');
        document.querySelector('body').appendChild(div);
        div.appendChild(visible = document.createElement('div'));
        visible.style       = 'border: 1px solid black; margin: 5px; display: inline-block;';
        visible.textContent = 'visible';
        div.appendChild(inViewport = visible.cloneNode(false));
        inViewport.textContent = 'inViewport';
        div.appendChild(notDisplayed = visible.cloneNode(false));
        notDisplayed.style.display = 'none';
        notDisplayed.textContent   = 'notDisplayed';
        div.appendChild(notVisible = visible.cloneNode(false));
        notVisible.style.visibility = 'hidden';
        notVisible.textContent      = 'notVisible';
        div.appendChild(leftOfViewport = visible.cloneNode(false));
        leftOfViewport.style.position = 'absolute';
        leftOfViewport.style.right = '100000px';
        leftOfViewport.textContent = 'leftOfViewport';
        div.appendChild(rightOfViewport = leftOfViewport.cloneNode(false));
        rightOfViewport.style.right       = '0';
        rightOfViewport.style.left       = '100000px';
        rightOfViewport.textContent = 'rightOfViewport';
        div.appendChild(aboveViewport = leftOfViewport.cloneNode(false));
        aboveViewport.style.right       = '0';
        aboveViewport.style.bottom       = '100000px';
        aboveViewport.textContent = 'aboveViewport';
        div.appendChild(belowViewport = leftOfViewport.cloneNode(false));
        belowViewport.style.right       = '0';
        belowViewport.style.top       = '100000px';
        belowViewport.textContent = 'belowViewport';
        div.appendChild(zeroOpacity = visible.cloneNode(false));
        zeroOpacity.textContent   = 'zeroOpacity';
        zeroOpacity.style.opacity = '0';
        div.appendChild(zIndex1 = visible.cloneNode(false));
        zIndex1.textContent = 'zIndex1';
        zIndex1.style.position = 'absolute';
        zIndex1.style.left = zIndex1.style.top = zIndex1.style.width = zIndex1.style.height = '100px';
        zIndex1.style.zIndex = '1';
        div.appendChild(zIndex2 = zIndex1.cloneNode(false));
        zIndex2.textContent = 'zIndex2';
        zIndex2.style.left = zIndex2.style.top = '90px';
        zIndex2.style.width = zIndex2.style.height = '120px';
        zIndex2.style.backgroundColor = 'red';
        zIndex2.style.zIndex = '2';
    });
    after(() => {
        div.parentNode.removeChild(div);
    });
    it('isVisible = true', () => {
        expect(isVisible(div)).to.be.true;
        expect(isVisible(visible)).to.be.true;
        expect(isVisible(inViewport)).to.be.true;
        expect(isVisible(zIndex2)).to.be.true;
    });
    it('isVisible = false', () => {
        expect(isVisible(notDisplayed)).to.be.false;
        expect(isVisible(notVisible)).to.be.false;
        expect(isVisible(document.createElement('div'))).to.be.false;
        expect(isVisible(zIndex1)).to.be.false;
        expect(isVisible(zeroOpacity)).to.be.false;
        expect(isVisible(leftOfViewport)).to.be.false;
        expect(isVisible(rightOfViewport)).to.be.false;
        expect(isVisible(aboveViewport)).to.be.false;
        expect(isVisible(belowViewport)).to.be.false;
    });
});
Ohad Navon
fonte
uma aresta caso o elem esteja posicionado fora da janela de visualização, pode ser capturado por "if (! pointContainer) return false;" verificando o primeiro pointContainer
Jerry Deng
Se você quiser verificar se o usuário pode vê-lo, você teria que usar um scrollIntoViewdireito ?! Isso é muito caro. Existe outra maneira inteligente?
Kim Kern
36

Isso pode ajudar: Esconda o elemento posicionando-o na posição mais à esquerda e verifique a propriedade offsetLeft. Se você deseja usar o jQuery, basta verificar : seletor e obter o estado de visibilidade do 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

Md. Ashaduzzaman
fonte
12
O OP solicita uma resposta no-jQuery.
Stephen Quan
Foi editado mais tarde, eu acho. Quando respondi, não foi mencionado no tópico.
Md. Ashaduzzaman
2
@StephenQuan, atualizei a resposta com as soluções jQuery e javaScript.
Md. Ashaduzzaman
6
para o exemplo do jQuery, o alerta não deveria dizer "Div is visible?"
Andrei Bazanov
Eu não gostaria de concluir que um elemento está totalmente oculto apenas porque seu offsetLeft é menor que 0: e se for apenas um pequeno número de pixels menor que 0 e sua parte direita estiver visível? (Eu concordo que isso parece um design tolo, mas você nunca conhece os designers da Web hoje em dia.) Provavelmente é melhor adicionar a largura ao offsetLeft e ver se o resultado ainda é menor que 0. Só por precaução.
Silas S. Brown
31

Use o mesmo código que o jQuery:

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

Então, em uma função:

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

Funciona como um encanto no meu Win / IE10, Linux / Firefox.45, Linux / Chrome.52 ...

Muito obrigado ao jQuery sem o jQuery!

Yvan
fonte
Bom, mas não cobre elementos ocultos pelo estouro.
Alph.Dev
legal mas e por que !! (dupla negação)?
Sunil Garg
3
Para forçar o resultado como booleano. Como e.offsetWidthé um número inteiro, !e.offsetWidthretornará falsese e.offsetWidthfor maior que zero (o elemento é visível). Portanto, adicionar outro !como em !!e.offsetWidthretornará truese e.offsetWidthfor maior que zero. É uma abreviação para return e.offsetWidth > 0 ? true : falseou obviamente return e.offsetWidth > 0.
Yvan
16

Combinando algumas respostas acima:

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

Como AlexZ disse, isso pode ser mais lento do que algumas de suas outras opções, se você souber mais especificamente o que está procurando, mas isso deve capturar todas as principais maneiras pelas quais os elementos estão ocultos.

Mas também depende do que é visível para você. Apenas por exemplo, a altura de uma div pode ser definida como 0px, mas o conteúdo ainda é visível, dependendo das propriedades do estouro. Ou o conteúdo de uma div pode ter a mesma cor do plano de fundo, para que não fique visível para os usuários, mas ainda seja renderizado na página. Ou uma div pode ser movida para fora da tela ou oculta por trás de outras divs, ou seu conteúdo pode não ser visível, mas a borda ainda visível. Até certo ponto, "visível" é um termo subjetivo.

Mateus
fonte
11
Bom, mas style.opacity, style.height e regresso style.width uma corda para que ele não irá trabalhar com ==!
Maslow
Outra maneira de ocultar um elemento por meio do estilo é que a cor pode corresponder à cor do plano de fundo ou o índice z pode ser menor que outros elementos.
nu everest
adicionar display:nonea isso seria ótimo. Uma solução de trabalho adequada!
Gijo Varghese
7

Eu tenho uma solução com melhor desempenho em comparação com a solução getComputedStyle () da AlexZ quando alguém tem elementos de posição 'fixos', se estiver disposto a ignorar alguns casos extremos (verifique os comentários):

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 lateral: Estritamente falando, a "visibilidade" precisa ser definida primeiro. No meu caso, estou considerando um elemento visível, desde que eu possa executar todos os métodos / propriedades do DOM nele sem problemas (mesmo se a opacidade for 0 ou a propriedade de visibilidade CSS estiver 'oculta' etc.).

Munawwar
fonte
6

Se o elemento estiver visível regularmente (display: block e visibillity: visible), mas algum contêiner pai estiver oculto, podemos usar clientWidth e clientHeight para verificar isso.

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

Plunker (clique aqui)

Vlada
fonte
ele.style.visibility !== 'hidden'é redundante aqui. Nesse caso, clientWidth e clientHeight será 0.
subdavis
5

Se estamos apenas coletando maneiras básicas de detectar visibilidade, não esqueço:

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

E sobre como obter atributos:

element.getAttribute(attributename);

Então, no seu exemplo:

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

Mas o que? Não funciona aqui. Olhe mais de perto e você verá que a visibilidade está sendo atualizada não como um atributo no elemento, mas usando a stylepropriedade Esse é um dos muitos problemas ao tentar fazer o que você está fazendo. Entre outros: você não pode garantir que realmente haja algo para ver em um elemento, apenas porque sua visibilidade, exibição e opacidade têm os valores corretos. Ele ainda pode não ter conteúdo ou pode não ter altura e largura. Outro objeto pode obscurecê-lo. Para mais detalhes, uma rápida pesquisa no Google revela isso e até inclui uma biblioteca para tentar resolver o problema. (YMMV)

Confira o seguinte, que são possíveis duplicatas desta pergunta, com excelentes respostas, incluindo algumas dicas do poderoso John Resig. No entanto, seu caso de uso específico é um pouco diferente do padrão, portanto evitarei sinalizar:

(EDIT: OP diz que ele está raspando páginas, não as criando, então abaixo não é aplicável) Uma opção melhor? Vincule a visibilidade dos elementos às propriedades do modelo e sempre torne a visibilidade contingente nesse modelo, da mesma forma que o Angular faz com o ng-show. Você pode fazer isso usando qualquer ferramenta que desejar: JS angular e simples, qualquer que seja. Melhor ainda, você pode alterar a implementação do DOM ao longo do tempo, mas sempre poderá ler o estado do modelo, em vez do DOM. Ler a sua verdade a partir do DOM é ruim. E devagar. Muito melhor verificar o modelo e confiar na sua implementação para garantir que o estado do DOM reflita o modelo. (E use o teste automatizado para confirmar essa suposição.)

XML
fonte
Eu estou analisando sites, isso não é para o meu próprio site ... :)
Hommer Smith
4

A resposta aceita não funcionou para mim. Resposta do ano 2020 :

1) O método (elem.offsetParent! == null) funciona bem no Firefox, mas não no Chrome. Para o Chrome "position: fixed;" também fará com que offsetParent retorne "null", mesmo o elemento se visível na página.

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>

você pode ver esse cara megatest https://stackoverflow.com/a/11639664/4481831 (execute-o com vários navegadores para ver as diferenças).

2) O (getComputedStyle (elem) .display! == 'none') não funciona porque o elemento pode ser invisível porque uma das propriedades de exibição dos pais está configurada como none, getComputedStyle não irá capturar isso.

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) O (elem.clientHeight! == 0) . Este método não é influenciado pela posição fixa e também verifica se os pais do elemento não são visíveis. Mas tem problemas com elementos simples que não têm um layout css, veja mais aqui

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) Os (elem.getClientRects (). Length! == 0) que parecem ultrapassar os problemas dos três métodos anteriores. No entanto, há problemas com elementos que usam truques CSS (exceto "display: none") para ocultar na página.

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>

CONCLUSÃO: Então, o que eu mostrei é que nenhum método é perfeito. Para fazer uma verificação de visibilidade adequada, você deve usar uma combinação dos três últimos métodos.

crisc82
fonte
3

Apenas para referência, note-se que getBoundingClientRect()pode funcionar em certos casos.

Por exemplo, uma verificação simples de que o elemento está oculto display: nonepode se parecer com o seguinte:

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

Isso também é útil, pois também abrange largura zero, altura zero e position: fixedestojos. No entanto, ele não deve relatar elementos ocultos com opacity: 0ou visibility: hidden(mas nem o faria offsetParent).

encarnar
fonte
Melhor resposta para mim ... simples e eficaz. E nenhuma votação única após 3 anos! Continua mostrando o valor da "sabedoria da multidão". Minha versão: var isVisible = el => (r => r.width && r.height)(el.getBoundingClientRect());. Em seguida, pode filtrar matrizes de elementos da seguinte maneira: $$(sel).filter(isVisible).
7vujy0f0hy
Acho que é a mais simples solução developer.mozilla.org/en-US/docs/Web/API/Element/...
Marian07
Isso não funciona quando visível para o usuário .... se você rolar longe ele vai permanecer fiel
Ray Foss
3

Então, o que eu achei é o método mais viável:

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

Isso se baseia nesses fatos:

  • Um display: noneelemento (mesmo um aninhado) não tem largura nem altura.
  • visiblityé hiddenuniforme para elementos aninhados.

Portanto, não há necessidade de testar offsetParentou fazer um loop na árvore DOM para testar qual pai possui visibility: hidden. Isso deve funcionar mesmo no IE 9.

Você poderia argumentar se opacity: 0e os elementos recolhidos (tem largura, mas não altura - ou vice-versa) também não são realmente visíveis. Mas, novamente, eles não estão escondidos.

Tokimon
fonte
3

Um pequeno acréscimo à resposta do ohad navon.

Se o centro do elemento pertencer a outro elemento, não o encontraremos.

Portanto, para garantir que um dos pontos do elemento seja visível

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

Melhorando a resposta de @Guy Messika acima , quebrando e retornando false se o ponto central 'X for <0 estiver errado, pois o elemento do lado direito pode entrar na visualização. aqui está uma correção:

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
fonte
2

O código jQuery de http://code.jquery.com/jquery-1.11.1.js possui um parâmetro 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 );
};

Parece que há uma verificação extra relacionada ao documento do proprietário

Gostaria de saber se isso realmente captura os seguintes casos:

  1. Elementos ocultos atrás de outros elementos baseados em zIndex
  2. Elementos com transparência total tornando-os invisíveis
  3. Elementos posicionados fora da tela (ou seja, à esquerda: -1000px)
  4. Elementos com visibilidade: oculto
  5. Elementos com display: nenhum
  6. Elementos sem texto ou subelementos visíveis
  7. Elementos com altura ou largura definidos como 0
Scott Izu
fonte
0

Aqui está o código que escrevi para encontrar o único visível entre alguns elementos semelhantes e retornar o valor do atributo "class" sem o 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");
    }
  }
não especificado
fonte
0

Isto é o que eu fiz:

HTML e CSS: ocultou o elemento por padrão

<html>
<body>

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

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

</body>
</html> 

JavaScript: Adicionado um código para verificar se a visibilidade está oculta ou não:

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

Esta é uma maneira de determiná-lo para todas as propriedades do CSS, incluindo a visibilidade:

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

Ele funciona para qualquer propriedade css e é muito versátil e confiável.

William Green
fonte