Display: none, opacity: 0 e visibility: hidden
Tags: braziliandevs, css, frontend, webdev
Published: 2023-03-08 18:37:45

Continuando a saga das dúvidas e temores em <abbr title="Cascading Style Sheets">CSS</abbr>, hoje trago um assunto que foi sugerido por um colega um tempo atrás. Bora direto falar sobre como `display: none`, `visibility: hidden` e `opacity: 0` atuam no CSS pra dar aquela escondida nos elementos do seu layout!

> _**Sumário**_
> _[Display: none](#display-none)_
> _[Visibility: hidden](#visibility-hidden)_
> _[Opacity: 0](#opacity-0)_
> _[Casos de uso](#casos-de-uso)_

![Drax, personagem da Marvel, sendo invisível](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4wwbsnfqi0s32ks3bd8.gif)

---

## Display: none

[Em um outro artigo](https://dev.to/sucodelarangela/entendendo-css-display-inline-block-e-inline-block-lic#o-que-%C3%A9-o-display) que escrevi por aqui, a gente entendeu que o **display** identifica como vai ser a renderização dos elementos na tela, sendo que o _browser_ por si só já tem `block` e `inline` como displays padrões. O fato é que <mark>todo elemento renderizado em tela vai ter um **display** específico,</mark> e se você não atribuir um, ele vai assumir um dos padrões do _browser_.

A partir daqui, fica fácil a gente identificar o que acontece se você definir que um certo elemento não vai ter **nenhum display**: o elemento vai sumir da tela. E é exatamente isso que o `display: none` faz!

Mais do que fazer o elemento sumir da tela, o `display: none` vai fazer com que esse elemento sequer seja renderizado no <abbr title="Document Object Model">DOM</abbr>. Ou seja, esse elemento simplesmente <mark>não vai existir</mark> na árvore de elementos do seu <abbr title="Hyper Text Markup Language">HTML</abbr> e só vai ser renderizado quando você mudar a propriedade **display** pra algum outro valor.

Logo:

- `display: none` remove o elemento (e seus filhos) do DOM; e
- como esse elemento deixa de existir no HTML, ele também deixa de ocupar espaço no layout.

<figure>
![Nick Fury, da Marvel, desaparecendo com o estalo de Thanos](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxqx6sbi44pil4bx2dxt.gif)
<figcaption>Aplicaram display: none no Nick Fury</figcaption>
</figure>

---

## Visibility: hidden

A propriedade e seu valor aqui já dizem de cara o que ela faz: ela <mark>altera a visibilidade do elemento,</mark> deixando-o **escondido** (_hidden_, em inglês).

Porém, ao contrário do `display: none`, o elemento com `visibility: hidden` <mark>**permanece** na sua árvore de elementos do HTML,</mark> então mesmo que ele não apareça na página, ele continua ocupando o espaço reservado pra ele no seu layout.

Uma outra característica do `visibility: hidden` é que, por ele estar **invisível** na tela, esse elemento perde sua interatividade (o que faz total sentido), ou seja, se ele tiver um evento de clique, por exemplo, você não conseguirá usar esse clique até que você mude a visibilidade dele para `visible`.

Logo:

- `visibility: hidden` esconde o elemento na tela, mas não o remove do DOM;
- por ainda estar no DOM, apesar de invisível, o elemento ainda ocupa espaço na tela; e
- por estarem invisíveis, os elementos não são interativos, ou seja, o usuário não pode manipulá-los em tela.

<figure>
![Sheila, de Caverna do Dragão, desaparecendo com sua capa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fojwn0kmwpg34cn414w1.gif)
<figcaption>Can't touch me ♫</figcaption>
</figure>

---

## Opacity: 0

O `opacity: 0` talvez seja o que gere mais confusão na cabeça da galera porque, visualmente, ele não possui diferença alguma do `visibility: hidden`: o elemento continua não sendo visto no seu layout, mas o espaço que ele ocupa permanece no seu layout e o elemento em si continua presente no seu HTML. Então, o que muda?

A grande diferença aqui é que, enquanto o `visibility: hidden` de fato **esconde** o seu elemento da tela, o `opacity: 0` <mark>apenas aplica uma transparência total</mark> no elemento. Ou seja, ele ainda está na sua página, só que transparente.

E como esse elemento ainda está ali no seu layout (apesar de você não conseguir vê-lo), ele ainda mantém sua interatividade! Então, se esse elemento tiver um evento de clique, mesmo com ele transparente na página, ainda é possível ativar tal evento.

Logo:

- `opacity: 0` não possui diferença **visual** em relação à `visibility: hidden`;
- no entanto, o elemento é interativo, ou seja, o usuário pode interagir com ele (afinal, ele não está invisível, está apenas transparente).

<figure>
![Predador, do filme Predador, ficando invisível](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vm9hj7dz0sz878vcbboh.gif)
<figcaption>O fato de você não enxergar não quer dizer que ele não está ali.</figcaption>
</figure>

---

## Casos de uso

Os casos de uso de cada propriedade aqui variam muito entre os desenvolvedores, mas alguns usos mais gerais e comuns são:

- Use `display: none` quando quiser que algo fique totalmente inacessível no seu HTML até que você diga o contrário. Ex: fechar uma modal ou popup, remover da tela um item de _todo list_ que foi concluído. O uso de `visibility: hidden` ou `opacity: 0` nesses elementos pode causar espaçamentos e comportamentos estranhos na sua página;
- Use `visibility: hidden` em combinação com `opacity: 0` quando quiser fazer animações em menus e links, por exemplo, pois a propriedade `display` não permite adicionar transições suaves nos elementos que aparecem e desaparecem, o efeito é totalmente brusco.

Para entender um pouco melhor esses comportamentos, experimente o Codepen abaixo à vontade:

{% codepen https://codepen.io/sucodelarangela/pen/RwYLEJV %}

Vale ressaltar a importância em relação à **Acessibilidade**: os elementos com `display: none` e `visibility: hidden` são totalmente ignorados pelos aplicativos leitores de tela, enquanto que elementos com `opacity: 0` são reconhecidos por eles. Fique atento ao correto uso dessas propriedades também quando se deparar com esse quesito! 😉

> _E a dica de milhões: caso você queira deixar algo totalmente escondido da tela, mas ainda permitir que os leitores de tela reconheçam esses elementos, sugiro criar no seu CSS a classe abaixo, cujo código foi extraído do [Tailwind](https://tailwindcss.com/docs/screen-readers)._

```css
.sr-only {
  position: absolute;
  height: 1px;
  width: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}
```

Essa classe vai usar todos os artifícios possíveis pra **garantir** que o elemento não esteja visível na tela, mas continue sendo acessado pelos leitores, como o NVDA. É um código muito útil quando você quer fazer um formulário sem `labels` visíveis, por exemplo: as `labels` estão no código, elas serão lidas para cada `input`, mas elas não estarão visíveis.

Espero que esse artigo te traga alguma luz sobre o assunto, jovem Padawan! Um xero!

**_Fontes:_**
- _[W3Schools](https://www.w3schools.com/css/tryit.asp?filename=trycss_display)_
- _[FreeCodeCamp](https://www.freecodecamp.org/news/css-display-none-and-visibility-hidden-the-difference/)_
- _[Tailwind](https://tailwindcss.com/docs/screen-readers)_