Como construir um modal pop-up JavaScript do zero

Neste tutorial aprenderemos como construir modais JavaScript (janelas pop-up) sem usar um framework como Bootstrap ou uma biblioteca de terceiros. Construiremos tudo do zero, dando-nos controle total sobre seu funcionamento e aparência.

1. Comece com a marcação da página

Primeiro vamos criar um modal. Para fazer isso, adicionaremos o .modal classe e um ID exclusivo para um contêiner. A seguir, especificaremos a caixa de diálogo definindo um .modal-dialog elemento como filho direto do .modal. A caixa de diálogo conterá o conteúdo modal. Pode ser qualquer tipo de conteúdo, como texto, imagens, lightboxes, notificações/alertas de usuário, etc.

“Um pop-up (ou modal) é um pequeno elemento de UI que aparecerá em primeiro plano de um site, geralmente acionado como um prompt para o usuário fazer algo” – Adi Purdila

Para abrir um modal, precisaremos de qualquer elemento com o data-open atributo (normalmente um button). O valor deste atributo deve ser o ID do modal desejado.

Por padrão, um modal será fechado se clicarmos fora de seus limites ou quando o Esc tecla é pressionada. Mas também podemos fechá-lo se clicarmos em qualquer elemento com o data-close atributo (normalmente um button).

Inicialmente o modal irá aparecer/desaparecer com um efeito de fade. Mas temos a capacidade de ajustar o efeito de animação do diálogo através do data-animation atributo. O valor deste atributo que deve ser adicionado ao .modal pode ser qualquer um dos seguintes valores:

  • slideInOutDown
  • slideInOutTop
  • slideInOutLeft
  • slideInOutRight
  • zoomInOut
  • rotateInOutDown
  • mixInAnimations

Veremos mais de perto esses valores em uma próxima seção.

Por enquanto, vamos nos familiarizar com a marcação necessária para representar um único modal:

1
 type="button" class="open-modal" data-open="modal1">...
2

3
 class="modal" id="modal1">
4
   class="modal-dialog">
5
     class="modal-header">
6
      ...
7
       class="close-modal" aria-label="close modal" data-close>
8
    
9
     class="modal-content">...
10
     class="modal-footer">...
11
  
12

2. Defina alguns estilos básicos

Com a marcação pronta, configuraremos algumas variáveis ​​CSS e redefiniremos estilos:

1
:root {
2
  --lightgray: #efefef;
3
  --blue: steelblue;
4
  --white: #fff;
5
  --black: rgba(0, 0, 0, 0.8);
6
  --bounceEasing: cubic-bezier(0.51, 0.92, 0.24, 1.15);
7
}
8

9
* {
10
  padding: 0;
11
  margin: 0;
12
}
13

14
button {
15
  cursor: pointer;
16
  background: transparent;
17
  border: none;
18
  outline: none;
19
  font-size: inherit;
20
}

A seguir, centralizaremos o conteúdo da página horizontal e verticalmente. Além disso, daremos alguns estilos ao botão responsável por abrir o modal:

1
/*CUSTOM VARIABLES HERE*/
2

3
body {
4
  display: flex;
5
  align-items: center;
6
  justify-content: center;
7
  height: 100vh;
8
  font: 16px/1.5 sans-serif;
9
}
10

11
.btn-group {
12
  text-align: center;
13
}
14

15
.open-modal {
16
  font-weight: bold;
17
  background: var(--blue);
18
  color: var(--white);
19
  padding: .75rem 1.75rem;
20
  margin-bottom: 1rem;
21
  border-radius: 5px;
22
}

Neste ponto focaremos nossa atenção nos estilos modais.

Cada modal terá os seguintes características:

  • Será em tela cheia com uma posição fixa. Dito isto, parecerá uma sobreposição que cobre toda a largura e altura da janela.
  • Terá uma cor de fundo escura.
  • Ele ficará oculto por padrão.
  • A caixa de diálogo será centralizada horizontal e verticalmente.
1
/*CUSTOM VARIABLES HERE*/
2

3
.modal { 
4
  position: fixed;
5
  top: 0;
6
  left: 0;
7
  right: 0;
8
  bottom: 0;
9
  display: flex;
10
  align-items: center;
11
  justify-content: center;
12
  padding: 1rem;
13
  background: var(--black);
14
  cursor: pointer;
15
  visibility: hidden;
16
  opacity: 0;
17
  transition: all 0.35s ease-in;
18
}

A caixa de diálogo terá uma largura máxima e uma altura máxima. Sua altura será 80% da altura da janela. Nos casos em que sua altura ultrapasse esse valor, aparecerá uma barra de rolagem vertical:

1
/*CUSTOM VARIABLES HERE*/
2

3
.modal-dialog {
4
  position: relative;
5
  max-width: 800px;
6
  max-height: 80vh;
7
  border-radius: 5px;
8
  background: var(--white);
9
  overflow: auto;
10
  cursor: default;
11
}

Por último, definiremos alguns estilos simples para as seções de conteúdo individuais:

1
/*CUSTOM VARIABLES HERE*/
2

3
.modal-dialog > * {
4
  padding: 1rem;
5
}
6

7
.modal-header,
8
.modal-footer {
9
  background: var(--lightgray);
10
}
11

12
.modal-header {
13
  display: flex;
14
  align-items: center;
15
  justify-content: space-between;
16
}
17

18
.modal-header .modal-close {
19
  font-size: 1.5rem;
20
}
21

22
.modal p + p {
23
  margin-top: 1rem;
24
}

3. Alternar Modal JavaScript

Uma página pode ter mais de um modal JavaScript. Mas, como já discutido anteriormente, todos os modais ficarão inicialmente ocultos.

Abra o Modal JavaScript

Da mesma forma, uma página pode ter mais de um gatilho aberto (elementos com o data-open atributo). Cada vez que um gatilho é clicado, o modal associado deve ficar visível com uma animação fade-in. Lembre o data-open o valor do atributo deve corresponder ao ID de um modal.

Aqui está o script que revela um modal:

1
const openEls = document.querySelectorAll("[data-open]");
2
const isVisible = "is-visible";
3

4
for(const el of openEls) {
5
  el.addEventListener("click", function() {
6
    const modalId = this.dataset.open;
7
    document.getElementById(modalId).classList.add(isVisible);
8
  });
9
}

E as classes CSS relevantes:

1
.modal {
2
  visibility: hidden;
3
  opacity: 0;
4
  transition: all 0.35s ease-in;
5
}
6

7
.modal.is-visible {
8
  visibility: visible;
9
  opacity: 1;
10
}

Fechar Modal JavaScript

Com nossa implementação, apenas um modal pode aparecer por vez (este código não oferece suporte a modais aninhados). Conforme mencionado na seção de marcação acima, existem três métodos disponíveis para ocultá-lo com um efeito de fade-out.

Vamos recapitular.

Em primeiro lugar, clicando no personalizado [data-close] elemento que está localizado dentro do modal:

1
const closeEls = document.querySelectorAll("[data-close]");
2
const isVisible = "is-visible";
3

4
for (const el of closeEls) {
5
  el.addEventListener("click", function() {
6
    this.parentElement.parentElement.parentElement.classList.remove(isVisible);
7
  });
8
}

Em segundo lugar, clicando em tudo fora do modal:

1
const isVisible = "is-visible";
2

3
document.addEventListener("click", e => {
4
  if (e.target == document.querySelector(".modal.is-visible")) {
5
    document.querySelector(".modal.is-visible").classList.remove(isVisible);
6
  }
7
});

Neste caso o modal (overlay) se comporta como um botão gigante de fechar. Por esta razão nós demos cursor: pointer.

Por último, pressionando o Esc chave:

1
const isVisible = "is-visible";
2

3
document.addEventListener("keyup", e => {
4
  if (e.key == "Escape" && document.querySelector(".modal.is-visible")) {
5
    document.querySelector(".modal.is-visible").classList.remove(isVisible);
6
  }
7
});

Agora é um bom momento para ver o que criamos até agora:

O modal parece muito bom! Observe que cada vez que clicamos em um gatilho aberto, apenas os modais correspondentes são carregados.

Vamos dar um passo adiante e examinar algumas idéias para animar seu diálogo.

4. Adicionar animações de diálogo

Como dissemos anteriormente, o comportamento padrão do modal é aumentar e diminuir gradualmente. Mas existe a opção de ajustar o efeito de animação do pop-up.

Já criei vários efeitos de animação que você pode usar como alternativa ao efeito fade. Para isso, basta passar o data-animation="yourDesiredAnimation" atribuir ao .modal.

Por exemplo, se quiser que a caixa de diálogo apareça com uma animação de slide da esquerda para a direita, você precisará do slideInOutLeft efeito.

Nos bastidores, existem duas regras que realizam a animação desejada:

1
/*CUSTOM VARIABLES HERE*/
2

3
[data-animation="slideInOutLeft"] .modal-dialog {
4
  opacity: 0;
5
  transform: translateX(-100%);
6
  transition: all 0.5s var(--bounceEasing);
7
}
8

9
[data-animation="slideInOutLeft"].is-visible .modal-dialog {
10
  opacity: 1;
11
  transform: none;
12
  transition-delay: 0.2s;
13
}

Confira o modal com esse tipo de animação aqui:

Você pode conferir o resto das animações olhando o CSS guia do projeto de demonstração final. Dependendo da complexidade das animações, usei transições CSS ou animações para construí-las.

Eu também fiz uso do cubic-bezier() função para definir a função de tempo para todas as transições. Se você não gostar do efeito de salto produzido, sinta-se à vontade para alterá-lo para algo mais suave por meio do --bounceEasing Variável CSS.

Dê uma olhada na demonstração final com todos os efeitos de animação aqui:

Conclusão

É isso, pessoal! Durante este tutorial, aprendemos como construir caixas de diálogo modais JavaScript animadas e personalizadas sem depender de qualquer estrutura de front-end. Espero que você tenha gostado do resultado final e que construí-lo tenha ajudado a atualizar suas habilidades de front-end.

Tenha em mente que não consideramos a acessibilidade, então se você quiser aprimorar esta demonstração esse certamente poderá ser o próximo passo.

Como sempre, obrigado pela leitura!

Mais leitura pop-up

Deixe uma resposta