Ocultando Elementos no CSS: none vs hidden | Web Academy
Fazer um elemento desaparecer de uma página web parece uma tarefa trivial à primeira vista. No entanto, no CSS, a palavra “invisível” esconde armadilhas profundas: o elemento deve sumir e ceder seu espaço geométrico aos vizinhos? Ele deve permanecer ocupando uma lacuna vazia? Usuários com leitores de tela devem continuar ouvindo esse conteúdo? O elemento pode receber cliques do mouse mesmo invisível? Nesta lição, você dominará as diferenças arquiteturais entre display: none, visibility: hidden, opacity: 0 e aprenderá a consagrada técnica moderna .visually-hidden para acessibilidade profissional.
📑 Índice do Conteúdo
1. A Mecânica de Ocultação: Render Tree, Layout e Acessibilidade
Para compreender como o CSS oculta nós, precisamos olhar para as entranhas do motor de renderização do navegador (Blink, Gecko, WebKit). A pipeline de exibição divide o documento em estruturas distintas:
- DOM Tree (Árvore DOM): A representação pura dos nós HTML na memória. Nenhum comando de CSS remove nós da DOM Tree (apenas scripts JavaScript com
remove()fazem isso). - Render Tree (Árvore de Renderização): A fusão da árvore DOM com as regras de CSS computadas. Elementos que não produzem caixas visuais nem afetam a geometria são sumariamente eliminados desta árvore.
- Layout / Reflow (Cálculo Geométrico): O cálculo das coordenadas cartesianas (X, Y) e das dimensões exatas de cada retângulo na tela.
- Accessibility Tree (Árvore de Acessibilidade): A estrutura lida por leitores de tela (NVDA, VoiceOver, JAWS) e tecnologias assistivas.
Regra Fundamental: Toda vez que você escolhe como esconder uma caixa, você está decidindo se ela é expulsa da Render Tree, se permanece no cálculo de Layout ou se é eliminada da Accessibility Tree.
2. display: none — O Desaparecimento Total do Fluxo
Quando aplicamos display: none a um elemento, o navegador o desativa completamente da Render Tree. O elemento continua existindo no código HTML e na memória JavaScript (DOM), mas para o motor de layout e pintura, ele simplesmente não existe:
.painel-desativado {
display: none;
}
Principais Consequências de display: none:
- Liberação Espacial Absoluta: O elemento não ocupa nenhuma largura, altura, margem ou borda. Os elementos vizinhos se reorganizam imediatamente para ocupar o espaço que antes pertencia a ele, provocando um processo de reflow (recálculo geométrico geral).
- Bloqueio de Herança aos Filhos: Se uma
<div>pai temdisplay: none, nenhum nó descendente poderá ser exibido, mesmo que você declaredisplay: block !importantno elemento filho. A caixa raiz do ramo foi destruída da árvore de renderização. - Invisibilidade para Leitores de Tela: Elementos com
display: nonesão sumariamente removidos da Árvore de Acessibilidade. Deficientes visuais não conseguem navegar nem ouvir o conteúdo desse nó. - Impossibilidade de Transições Suaves: A propriedade
displaynão é interpolável numericamete. Você não pode animar suavemente dedisplay: noneparadisplay: blockcomtransitioncomum (a menos que use recursos experimentais recentes do CSS Display Level 4 comotransition-behavior: allow-discretee@starting-style).
3. visibility: hidden — A Cortina de Invisibilidade Geométrica
Diferente de display: none, a propriedade visibility: hidden não expulsa o elemento da etapa de Layout. Ela apenas instrui o motor gráfico a não pintar os pixels da caixa na tela:
.espaco-reservado {
visibility: hidden;
}
Comportamentos Únicos de visibility: hidden:
- Preservação Rígida do Espaço: O elemento continua ocupando exatamente sua largura, altura, padding e margens no fluxo do documento. Cria-se um “buraco invisível” na página, e os elementos irmãos permanecem exatamente onde estavam, sem sofrer reflow geométrico.
- Isenção de Cliques e Foco: Embora ocupe espaço na tela, o elemento invisível não intercepta cliques de mouse nem recebe foco via teclado (a tecla
Tabpula essa caixa). - A Grande Exceção: Filhos Podem Reaparecer! Ao contrário de
display, a propriedadevisibilityé herdada por padrão, mas pode ser sobrescrita em qualquer filho. Se um pai forvisibility: hiddene um elemento filho tivervisibility: visible, o filho reaparece flutuando perfeitamente no meio do vazio deixado pelo pai!
/* O pai fica invisível mas reserva 300px na tela */
.menu-pai {
visibility: hidden;
width: 300px;
height: 200px;
background-color: #0f172a;
}
/* O filho reaparece normalmente no meio da área vazia */
.menu-pai .item-ativo {
visibility: visible;
background-color: #10b981;
color: #ffffff;
}
4. opacity: 0 vs. O Perigo dos Fantasmas Clicáveis
Definir opacity: 0 torna a caixa 100% transparente. No entanto, aos olhos do navegador, o elemento continua ativo e interativo:
.botao-fantasma {
opacity: 0;
/* PERIGO: continua ocupando espaço e recebendo cliques acidentais! */
}
Atenção Crítica: Se você apenas aplicar opacity: 0 em um botão, o usuário não verá o botão, mas ao passar o mouse por cima do espaço vazio, o cursor virará uma mãozinha (pointer) e, se clicar, disparará o evento de clique! Além disso, a navegação via teclado com Tab continuará caindo em um botão invisível.
Para desativar a interação em elementos tornados transparentes com opacity: 0 (muito comuns em modais e dropdowns com transição suave), você deve associar pointer-events: none:
/* Modal fechado com transição de opacidade segura */
.modal-overlay {
opacity: 0;
pointer-events: none; /* Desativa cliques do mouse */
transition: opacity 0.3s ease;
}
/* Modal aberto */
.modal-overlay.is-active {
opacity: 1;
pointer-events: auto; /* Reativa os cliques */
}
5. O Dilema da Acessibilidade: O que os Leitores de Tela Enxergam?
Para criar interfaces inclusivas em conformidade com as diretrizes internacionais WCAG 2.2, precisamos saber exatamente como as tecnologias assistivas reagem a cada método de ocultação:
| Propriedade | Visível na Tela? | Ocupa Espaço Físico? | Detectado por Leitores de Tela? | Focável com Teclado (Tab)? |
|---|---|---|---|---|
display: none |
❌ Não | ❌ Não | ❌ Ignorado (Não lê) | ❌ Não |
visibility: hidden |
❌ Não | ✅ Sim (reserva vazio) | ❌ Ignorado (Não lê) | ❌ Não |
opacity: 0 |
❌ Não | ✅ Sim | ⚠️ Sim (Leitor lê normalmente!) | ⚠️ Sim (se não usar tabindex="-1") |
hidden (atributo HTML) |
❌ Não | ❌ Não | ❌ Ignorado (Não lê) | ❌ Não |
.visually-hidden (CSS) |
❌ Não | ❌ Não (1x1px colapsado) | ✅ Sim (Lê com perfeição!) | ✅ Acessível para auxílio |
6. A Técnica Moderna .visually-hidden (Screen Readers Only)
Muitas vezes, precisamos de um elemento invisível aos olhos de quem enxerga a tela, mas essencial para usuários cegos navegando via áudio. Exemplos clássicos incluem:
- O texto descritivo dentro de um botão que só tem um ícone de lupa (ex.:
<button><svg>...</svg><span class="visually-hidden">Pesquisar no site</span></button>). - Links de salto para o conteúdo principal (Skip to Content).
- Rótulos de cabeçalho ocultos para estruturar seções que no design usam apenas separadores visuais.
Técnicas antigas como text-indent: -9999px ou posicionamento left: -10000px causam problemas graves de performance, renderização fora de tela e falhas em dispositivos táteis. O padrão ouro adotado mundialmente (Bootstrap, Tailwind, WordPress Core) é o padrão clip-path / rect:
/* Classe utilitária universal de acessibilidade */
.visually-hidden,
.sr-only {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
border: 0 !important;
}
Essa combinação mágica reduz o elemento a uma caixa imperceptível de 1 pixel por 1 pixel, recorta sua renderização visual a zero, retira-o do fluxo para não deformar a grade da página e mantém o conteúdo 100% vivo e intacto dentro da Accessibility Tree.
7. Laboratório Prático: Comparando none, hidden e opacity
Veja no exemplo interativo abaixo como as três abordagens se comportam em um conjunto de caixas alinhadas. Observe atentamente o que acontece com os vizinhos quando uma caixa do meio é ocultada com cada método:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Laboratório de Ocultação CSS</title>
<style>
body {
font-family: 'Segoe UI', system-ui, sans-serif;
background: #0b0f19;
color: #f1f5f9;
padding: 30px;
}
.container {
display: flex;
gap: 16px;
background: #1e293b;
padding: 24px;
border-radius: 12px;
border: 1px solid #334155;
margin-bottom: 24px;
}
.card {
width: 120px;
height: 100px;
background: #2563eb;
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
border-radius: 8px;
text-align: center;
transition: opacity 0.4s ease;
}
/* 1. Desaparece e o Card 3 encosta no Card 1 (Reflow total) */
.modo-none {
display: none;
}
/* 2. Fica invisível, mas deixa um espaço vazio de 120px entre os Cards 1 e 3 */
.modo-hidden {
visibility: hidden;
}
/* 3. Fica transparente, continua ocupando 120px e pode ser clicado! */
.modo-opacity {
opacity: 0;
}
</style>
</head>
<body>
<h2>Demonstração Visual de Ocultação</h2>
<div class="container">
<div class="card">Card 1</div>
<!-- Mude a classe abaixo para .modo-none, .modo-hidden ou .modo-opacity -->
<div class="card modo-hidden">Card 2 (Oculto)</div>
<div class="card">Card 3</div>
</div>
</body>
</html>
Experimente alternar a classe do Card 2 no editor de código do nosso laboratório online para ver a mecânica de renderização em tempo real:
8. Resumo da Lição e Guia Rápido de Escolha
- Use
display: nonequando quiser remover um componente do fluxo e reorganizar a página (ex.: abas de navegação fechadas, acordeões colapsados, itens filtrados em uma busca). - Use
visibility: hiddenquando precisar que a página mantenha rigorosamente a estrutura espacial sem tremor de layout (ex.: placeholders de carregamento, animações de revelação geométrica, menus suspensos onde os filhos precisam reaparecer). - Use
opacity: 0+pointer-events: nonequando for criar transições e animações suaves de fade-in / fade-out (ex.: modais, popups, tooltips flutuantes). - Use
.visually-hiddensempre que um elemento for destinado exclusivamente a leitores de tela para prover acessibilidade e navegação sem poluir visualmente a interface gráfica.
Próximo Passo: Agora que você domina os tipos de exibição e como controlar o que aparece ou não na tela, na Lição 23 entraremos no coração dos layouts avançados: Posicionamento CSS (relative, absolute, fixed e sticky)!