Verificar se o elemento é visível no DOM

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

Assim, por exemplo, nesta página: Performance Bikes, se você pairar sobre os negócios (no menu superior), uma janela de negócios aparece, mas no início ela não foi mostrada. Ela está no HTML, mas não é visível.

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

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

mas parece que não... 39; não está a funcionar. Eu me pergunto quais atributos devo verificar. Isso vem-me à cabeça:

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

Há mais algum que possa estar desaparecido?

Solução

De acordo com esta documentação MDN, um elemento's offsetParent propriedade retornará null sempre que ele, ou qualquer um de seus pais, estiver escondido através da propriedade estilo display. Apenas certifique-se de que o elemento está't corrigido. Um script para verificar isso, se você não tiver position: fixed; elementos na sua página, pode ser parecido:

// 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ê * tem elementos fixos de posição que podem ficar presos nesta busca, você terá que utilizar window.getComputedStyle() infelizmente (e lentamente). 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 simples, uma vez que conta com mais casos de borda, mas aposto que é um bom negócio mais lento também, então se você tiver que repetir esta operação muitas vezes, o melhor é provavelmente evitá-la.

Comentários (19)

Isso pode ajudar : Ocultar o elemento posicionando-o na posição mais à esquerda e depois verificar a propriedade offsetLeft. Se quiser usar jQuery pode simplesmente verificar o :visible selector e obter o estado de visibilidade do elemento.

HTML :

<div id="myDiv">Hello</div>

CSS :


#myDiv{
   position:absolute;
   left : -2000px;
}


#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

Comentários (7)

Se nós'estamos apenas coletando formas básicas de detectar visibilidade, não me deixe esquecer:

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

E quanto a como obter atributos:

element.getAttribute(attributename);

Então, no seu exemplo:

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

Mas o quê? Não funciona aqui... 39; não funciona aqui. Olhe mais de perto e você'descobrirá que a visibilidade está sendo atualizada não como um atributo no elemento, mas utilizando a propriedade estilo. Este é um dos muitos problemas em tentar fazer o que você'está fazendo. Entre outros: você pode't garantir que lá'é realmente algo a ver em um elemento, só porque sua visibilidade, exibição, e opacidade todos 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 pesquisa rápida no Google revela isto, e até inclui uma biblioteca para tentar resolver o problema. (YMMV)

Confira a seguir, que são possíveis duplicatas desta pergunta, com excelentes respostas, incluindo algumas perspicazidades do poderoso John Resig. Entretanto, o seu caso de uso específico é ligeiramente diferente do caso padrão, então I'irá se abster de sinalizar:

(EDITAR: OP DIZ QUE ELE'S RASPANDO PÁGINAS, NÃO AS CRIANDO, ENTÃO ABAIXO É'T APLICÁVEL) Uma opção melhor? Ligue a visibilidade dos elementos às propriedades do modelo e faça sempre depender a visibilidade desse modelo, tal como a Angular faz com o ng-show. Você pode fazer isso usando qualquer ferramenta que você quiser: Angular, simples JS, o que quiser. Melhor ainda, você pode mudar a implementação do DOM ao longo do tempo, mas você'será sempre capaz de ler o estado do modelo, em vez do DOM. Ler a sua verdade a partir do DOM é mau. E lento. Muito melhor verificar o modelo, e confiar na sua implementação para assegurar que o estado do DOM reflecte o modelo. (E use testes automatizados para confirmar essa suposição).

Comentários (1)