Construindo uma modal semântica com o elemento <dialog>
Tags: braziliandevs, beginners, webdev, tutorial
Published: 2023-05-17 22:38:01

Construir um bom e velho **pop-up** na sua aplicação já foi bem mais difícil! Quer aprender uma forma mais simples e, o melhor de tudo, mais acessível de criar uma Modal na tua página web? Então, chega mais!

> _**Sumário**
> [Estrutura inicial](#estrutura-inicial)
> [O elemento &lt;dialog&gt;](#o-elemento-ltdialoggt)
> [Estilizando nossa Modal](#estilizando-nossa-modal)
> [Abrindo e fechando a Modal com JavaScript](#abrindo-e-fechando-a-modal-com-javascript)
> [Uma palavra sobre Acessibilidade](#uma-palavra-sobre-acessibilidade)
> [E só pra terminar](#e-só-pra-terminar)_

![Guaxinim surgindo na tela](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9c18x1smh4d83rj0jszp.gif)

---

### Estrutura inicial

Vamos começar criando uma página simples com:
- 01 parágrafo;
- 01 botão para abrir a Modal; e
- A Modal propriamente dita.

Normalmente, colocamos a estrutura da **Modal** ao final da estrutura da página, antes de fechar o `<body>`, apenas por uma questão de organização mesmo.

```html
<body>
  <main>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.</p>
    <button class="btn open">Abrir modal</button>
  </main>

  <!-- AQUI CRIAREMOS A MODAL -->
</body>
```

Vamos começar a criar a nossa **Modal** usando a tag genérica `<div>`. Você vai perceber que, à medida que vai escrevendo o código, a estrutura da sua **Modal** vai aparecer normalmente no fluxo da página. Não se preocupe com isso por enquanto, vamos focar em estruturar todo o conteúdo da **Modal** primeiro.

```html
  <div class="modal">
    <h2>Header da Modal</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    <form>
      <label for="name">Nome:</label>
      <input
        type="text"
        id="name"
        placeholder="Digite seu nome"
        required
      />
      <button type="submit">Enviar</button>
    </form>
    <button type="button" class="btn close">X</button>
  </div>
```

Vamos também adicionar alguns estilos nessa página:
```css
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500&display=swap");

body {
  background: #fafafa;
  height: 100vh;
  padding: 0 1rem;
}

body, button {
  font-family: "Poppins", sans-serif;
}

.btn {
  border: none;
  border-radius: 0.5rem;
  font-weight: 500;
  font-size: 1rem;
  background: #3485ff;
  color: #fafafa;
  transition: filter 0.2s;
  padding: 1rem 2rem;
  cursor: pointer;
}

.btn.close {
  display: flex;
  align-items: center;
  clip-path: circle();
  position: absolute;
  top: 2rem;  
  right: 2rem;
  height: 1rem;
  aspect-ratio: 1/1;
}

.btn:hover, .btn:focus, button:hover, button:focus {
  filter: brightness(1.2);
}
```

Esse é o resultado parcial do nosso código até agora:

![Estrutura inicial da página](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5m9mhwbhu9f5ae00e8g.JPG)

---

### O elemento &lt;dialog&gt;

Criada na atual versão do <abbr title="Hyper Text Markup Language">HTML</abbr>, [a tag `<dialog>`](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) é uma tag semântica para criação de caixas de diálogo, também conhecidas no mundo dev como Modal ou, mais popularmente, Pop-Ups.

Além de proporcionar uma melhor semântica e ajudar no <abbr title="Search Engine Optimization">[SEO](https://www.alura.com.br/artigos/seo-o-que-e-boas-praticas-ferramentas-estrategia)</abbr> da sua página, existem outras vantagens no uso da tag `<dialog>` em vez de uma simples `<div>`. Veremos a seguir algumas dessas vantagens!

No código da nossa **Modal**, vamos trocar a `div` por `dialog`. E só em fazer essa troca, já é possível ver uma consequência: toda a estrutura da **Modal** simplesmente sumiu da nossa página! Mas fique calmo, esse é o comportamento padrão: quando definimos uma `<dialog>` na página, o _browser_ automaticamente o coloca com `display: none`, fazendo-o desaparecer. Para visualizar a sua **Modal** enquanto trabalhamos nela, adicione o atributo `open` na tag `<dialog>`, dessa forma:

```html
  <dialog open class="modal">
    <!-- código interno da modal -->
  </dialog>
```

Podemos perceber que toda a estrutura da `<dialog>` agora já se mantém organizada dentro de um bloco definido por uma borda preta. Você pode retirar essa borda através do <abbr title="Cascading Style Sheets">CSS</abbr>, se desejar. Aqui nesse tutorial, manteremos dessa forma.

![Prévia da dialog na página](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ci9a92u9z46hnvp0nv2a.JPG)

> _**Observação:** O atributo `open` só vai ser usado nesse primeiro momento, enquanto estilizamos nossa **Modal**. Apesar de ela poder ser usada para a função de abrir e fechar a Modal, perdemos alguns vantagens da tag `<dialog>` ao fazer isso, portanto, faremos essa funcionalidade de outra forma mais à frente nesse tutorial!_

Agora, vamos estilizar nossa Modal!

---

### Estilizando nossa Modal

Agora chegamos na parte divertida, que é a estilização da nossa Modal. Vamos acrescentar:
- Uma cor de fundo, com a propriedade `background` (ou `background-color`);
- Uma borda arredondada, com `border-radius`;
- Um espaçamento entre borda e elementos internos, com `padding`;
- Um alinhamento de texto ao centro, com `text-align`; e
- Uma largura mínima para a `<dialog>`, que pode ser de 37rem ou 80%, **o que for menor**.

```css
.modal {
  background: #fafafa;
  border-radius: 0.5rem;
  padding: 2rem;
  text-align: center;
  width: min(37rem, 80%);
}
```

Agora, adicionaremos estilos aos elementos internos da Modal:

```css
.modal h2 {
  font-size: 1.5rem;
  font-weight: 700;
  margin: 0 0 0.75rem;
  color: #0d114f;
}

.modal p {
  margin-bottom: 1.5rem;
  color: #4d5e77;
}

.modal button {
  cursor: pointer;
}
```

E assim ficou nossa **Modal**, quase 100% pronta! A seguir, vamos trabalhar a abertura e fechamento dessa Modal com **JavaScript**!

![Dialog estilizada](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbqi90xxt15tjz0rcd12.JPG)

---

### Abrindo e fechando a Modal com JavaScript

Uma das vantagens mais legais em usar a tag `<dialog>` é que as coisas ficam bem mais simples no JavaScript! Em outra situação, teríamos que criar um estilo extra para uma classe `.active` ou `.open` e fazer uma função `.toggle()` pra ativar ou desativar essa classe e fazer a Modal aparecer e sumir.

Porém, quando usamos a tag `<dialog>`, podemos simplesmente usar os métodos `showModal()` e `close()`, nativos do JavaScript, para lidar com a abertura e fechamento da Modal. Vamos ver como fazer?

Nosso primeiro passo é capturar os elementos que vamos precisar no DOM e salvá-los em variáveis com o uso de `querySelector()`:

```js
// A modal em si
const modal = document.querySelector(".modal");

// O botão de Abrir Modal
const openModalBtn = document.querySelector(".open");

// O botão de Fechar Modal
const closeModalBtn = document.querySelector(".close");
```

Depois, vamos adicionar para cada botão um "escutador de eventos", que vai identificar quando o botão vai ser clicado e executar uma função de abrir ou fechar a Modal:

```js
/* Ao clicar no botão de Abrir Modal, executamos a função
showModal() na Modal: */
openModalBtn.addEventListener("click", () => modal.showModal());

/* Ao clicar no botão de Fechar Modal, executamos a função
close() na Modal */
closeModalBtn.addEventListener("click", () => modal.close());
```

A partir daqui, podemos voltar lá no nosso HTML e excluir o atributo `open` da nossa `<dialog>`, pois agora a abertura e fechamento da nossa Modal já está sendo gerenciada pelo JavaScript. Além disso, o uso de `dialog` em combinação com o método `showModal()` faz com que a Modal já permita, por padrão, o fechamento através da tecla `ESC`, sem nenhuma configuração adicional!

![Modal funcionando com JavaScript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nz2exvn8cdfporneo5w2.gif)

Na ilustração acima, é possível ver que temos um fundo um pouquinho mais escuro quando a Modal é aberta. Esse **overlay** também é adicionado automaticamente pela combinação de `<dialog>` com `showModal()` e **não aparece quando abrimos a Modal usando o atributo `open`**.

Para finalizar os estilos da nossa Modal, podemos fazer com que esse fundo fique um pouco mais escuro, deixando a Modal com mais destaque. Para estilizar esse **overlay**, faremos uso da [pseudo-classe](https://dev.to/sucodelarangela/entendendo-css-pseudo-classes-e-pseudo-elementos-b83) `::backdrop`. Vamos acrescentar o seguinte CSS em nosso projeto:

```css
.modal::backdrop {
  background: rgba(0, 0, 0, .7);
}
```

Isso vai fazer com que nosso **overlay** fique mais escuro e mais agradável:

![Dialog com fundo alterado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/omwmxu95nhf0ntkb2il4.JPG)

---

### Uma palavra sobre Acessibilidade

Quando criamos uma Modal, é imprescindível que tenhamos o cuidado de estruturá-la da maneira adequada, evitando problemas sérios de [Acessibilidade Web](https://www.alura.com.br/artigos/acessibilidade-digital-criar-conteudos-acessiveis-aprenda-7-dicas).

O uso da tag `<dialog>`, além de tornar sua Modal mais semântica, também a torna mais acessível aos leitores de tela e à navegação via teclado. Ela já traz por padrão algumas coisas que, anteriormente, precisávamos adicionar manualmente ao HTML, como os atributos `aria-modal="true"` e `role="dialog"`.

Outra coisa que a tag `<dialog>` faz por padrão é fazer com que todo o conteúdo da página principal fique **inerte**, ou seja, quando a Modal está aberta, os conteúdos da sua página que estejam **fora** da Modal não podem ser selecionados via _mouse_ ou tecla `TAB`, o que é excelente para a Acessibilidade. Quando não usamos `dialog`, precisamos fazer isso manualmente através do JavaScript, o que gera bastante código extra.

<figure>
![Elementos inertes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8lcvnszf7w65iuly6im.gif)
<figcaption>Antes de abrir a Modal, os elementos são selecionáveis. Após abrir a Modal, não é possível selecionar o texto ou clicar no botão principal.</figcaption>
</figure>
>

Além de podermos fechar a modal com a tecla `ESC`, caso você tenha um formulário nessa Modal, a tag `dialog` também fecha automaticamente ela quando enviamos dados desse formulário, evitando termos que clicar em um botão de envio e, novamente, em outro botão para fechá-la. Para ativarmos essa funcionalidade, basta adicionarmos o atributo `method="dialog"` no nosso `<form>` (lembre-se que o botão de envio deve ser do tipo `submit`)

```html
<form method="dialog">
  <label for="name">Nome:</label>
  <input
    type="text"
    id="name"
    placeholder="Digite seu nome"
    required
  />
  <button type="submit">Enviar</button>
</form>
```

<figure>
![Fechamento da Modal no envio do formulário](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c35u28m6f6vvlkpt55nh.gif)
<figcaption>Ao enviar o formulário corretamente, a Modal fecha automaticamente.</figcaption>
</figure>
>

Para melhorar ainda mais a Acessibilidade da nossa Modal, vamos fazer mais duas pequenas alterações no nosso HTML. A primeira alteração será adicionar um atributo `aria-label` no nosso botão de Fechar Modal, pois o conteúdo textual dele é apenas um "X", e é isso que os leitores de tela vão falar para os usuários com deficiência visual, dificultando o entendimento do que aquele botão faz. Nosso botão ficará assim:

```html
<button type="button" class="btn close" aria-label="Fechar modal">X</button>
```

Agora, nosso leitor de tela vai ler "Fechar modal botão" em vez de "X botão". Muito mais claro, não?

A segunda alteração que faremos será no `<h2>`, que é o título principal da nossa Modal. Quando usamos a tag `dialog`, ao abrirmos a Modal, a página automaticamente foca nela e o leitor de tela anuncia que um "Diálogo" foi aberto, mas o ideal é que o usuário saiba de imediato do que se trata essa Modal.

Para isso, vamos usar nosso `h2` como título da nossa `dialog`, fazendo com que o leitor de tela anuncie corretamente nossa Modal com "Diálogo" mais o texto do H2. Só precisamos utilizar os atributos `aria-labelledby` na nossa `dialog` e vincularmos ela com uma `id` em nosso `h2`:

```html
<dialog class="modal" aria-labelledby="dialog-title">
  <h2 id="dialog-title">Header da Modal</h2>
  <!-- restante do código da Modal -->
</dialog>
```

Com isso, nós já deixamos nossa Modal bem mais acessível e agradável para uso de todos os usuários, o que chamamos na Arquitetura de [Desenho Universal](https://www.archdaily.com.br/br/992875/o-que-e-desenho-universal). 😉

---

### E só pra terminar...

Atualmente, a criação de Modal usando a tag `dialog` é nossa melhor opção em termos de funcionalidade e acessibilidade. Em combinação com o método `showModal()` do JavaScript, temos uma código mais limpo, mais organizado e uma implementação mais fácil!

Espero que com esse artigo, de aqui em diante seja mais fácil implementar caixas de diálogo nas suas aplicações e que isso te seja útil na sua evolução como Front Ender! Um xêro pra você!

>_E se quiser ver o código por completo, basta acessar o Codepen abaixo:_

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

---

_**Fontes**_
- [_W3C: Dialog (Modal) Pattern_](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)
- [_Angela Caldas: Entendendo CSS: Pseudo-Classes e Pseudo-Elementos_](https://dev.to/sucodelarangela/entendendo-css-pseudo-classes-e-pseudo-elementos-b83)
- [_Alura: Acessibilidade digital_](https://www.alura.com.br/artigos/acessibilidade-digital-criar-conteudos-acessiveis-aprenda-7-dicas)
- [_Alura: SEO: o que é, boas práticas e ferramentas estratégicas_](https://www.alura.com.br/artigos/seo-o-que-e-boas-praticas-ferramentas-estrategia)
- [_Kevin Powell: dialog = the easiest way to make a popup modal_](https://www.youtube.com/watch?v=TAB_v6yBXIE&ab_channel=KevinPowell)
- [_ArchDaily: Desenho Universal_](https://www.archdaily.com.br/br/992875/o-que-e-desenho-universal)