Aprenda como criar um modal com JavaScript puro usando o elemento nativo dialog, sem depender de bibliotecas externas como Bootstrap, jQuery ou plugins de interface.
Em muitos projetos, o modal é criado manualmente com div, overlay, controle de foco, eventos de clique fora da caixa e tratamento da tecla ESC. Isso funciona, mas aumenta a quantidade de código e pode gerar problemas de acessibilidade, principalmente quando o usuário continua conseguindo interagir com elementos atrás do modal.
Outro problema comum é o excesso de dependência de bibliotecas apenas para abrir uma janela modal simples. Em muitos casos, o próprio HTML já oferece uma solução nativa com o elemento dialog.
A Solução
A solução é usar o elemento HTML dialog junto com os métodos JavaScript showModal() e close(). Com isso, o navegador passa a tratar o modal de forma nativa, exibindo o conteúdo sobre a página e impedindo a interação com os elementos externos enquanto o modal estiver aberto.
Estrutura HTML do modal
Crie um botão para abrir o modal e, em seguida, adicione o elemento dialog com o conteúdo que será exibido.
<button type="button" class="btn-abrir-modal" data-modal-open="modalExemplo">
Abrir modal
</button>
<dialog id="modalExemplo" class="modal">
<div class="modal__conteudo">
<button type="button" class="modal__fechar" data-modal-close aria-label="Fechar modal">
&times;
</button>
<h2>Título do modal</h2>
<p>
Este é um exemplo de modal criado com JavaScript puro usando o elemento nativo dialog.
</p>
<div class="modal__acoes">
<button type="button" data-modal-close>
Fechar
</button>
</div>
</div>
</dialog> |
CSS para estilizar o modal
O pseudo-elemento ::backdrop permite estilizar o fundo escuro exibido atrás do modal.
.modal { width: min(90%, 500px); border: 0; border-radius: 12px; padding: 0; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35); } .modal::backdrop { background: rgba(0, 0, 0, 0.65); } .modal__conteudo { position: relative; padding: 24px; background: #fff; } .modal__fechar { position: absolute; top: 12px; right: 12px; border: 0; background: transparent; font-size: 28px; line-height: 1; cursor: pointer; } .modal__acoes { margin-top: 24px; text-align: right; } .btn-abrir-modal, .modal__acoes button { cursor: pointer; padding: 10px 16px; border: 0; border-radius: 6px; } |
JavaScript para abrir e fechar o modal
O método showModal() abre o modal em modo bloqueante. Já o método close() fecha o modal.
document.addEventListener('DOMContentLoaded', function () { const botoesAbrir = document.querySelectorAll('[data-modal-open]'); const botoesFechar = document.querySelectorAll('[data-modal-close]'); botoesAbrir.forEach(function (botao) { botao.addEventListener('click', function () { const modalId = botao.getAttribute('data-modal-open'); const modal = document.getElementById(modalId); if (!modal) { return; } if (!modal.open) { modal.showModal(); } }); }); botoesFechar.forEach(function (botao) { botao.addEventListener('click', function () { const modal = botao.closest('dialog'); if (modal) { modal.close(); } }); }); }); |
Fechar o modal ao clicar fora do conteúdo
Também é possível fechar o modal quando o usuário clicar na área escura fora da caixa principal. Para isso, verificamos se o clique aconteceu diretamente no elemento dialog.
document.addEventListener('DOMContentLoaded', function () { const modais = document.querySelectorAll('dialog'); modais.forEach(function (modal) { modal.addEventListener('click', function (event) { if (event.target === modal) { modal.close(); } }); }); }); |
Exemplo completo
Abaixo está um exemplo completo com HTML, CSS e JavaScript.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modal com JavaScript</title>
<style>
.modal {
width: min(90%, 500px);
border: 0;
border-radius: 12px;
padding: 0;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}
.modal::backdrop {
background: rgba(0, 0, 0, 0.65);
}
.modal__conteudo {
position: relative;
padding: 24px;
background: #fff;
font-family: Arial, sans-serif;
}
.modal__fechar {
position: absolute;
top: 12px;
right: 12px;
border: 0;
background: transparent;
font-size: 28px;
line-height: 1;
cursor: pointer;
}
.modal__acoes {
margin-top: 24px;
text-align: right;
}
.btn-abrir-modal,
.modal__acoes button {
cursor: pointer;
padding: 10px 16px;
border: 0;
border-radius: 6px;
}
</style>
</head>
<body>
<button type="button" class="btn-abrir-modal" data-modal-open="modalExemplo">
Abrir modal
</button>
<dialog id="modalExemplo" class="modal">
<div class="modal__conteudo">
<button type="button" class="modal__fechar" data-modal-close aria-label="Fechar modal">
&times;
</button>
<h2>Modal com JavaScript</h2>
<p>
Este modal foi criado usando JavaScript puro e o elemento nativo dialog.
</p>
<div class="modal__acoes">
<button type="button" data-modal-close>
Fechar
</button>
</div>
</div>
</dialog>
<script>
document.addEventListener('DOMContentLoaded', function () {
const botoesAbrir = document.querySelectorAll('[data-modal-open]');
const botoesFechar = document.querySelectorAll('[data-modal-close]');
const modais = document.querySelectorAll('dialog');
botoesAbrir.forEach(function (botao) {
botao.addEventListener('click', function () {
const modalId = botao.getAttribute('data-modal-open');
const modal = document.getElementById(modalId);
if (!modal) {
return;
}
if (!modal.open) {
modal.showModal();
}
});
});
botoesFechar.forEach(function (botao) {
botao.addEventListener('click', function () {
const modal = botao.closest('dialog');
if (modal) {
modal.close();
}
});
});
modais.forEach(function (modal) {
modal.addEventListener('click', function (event) {
if (event.target === modal) {
modal.close();
}
});
});
});
</script>
</body>
</html> |
Conclusão
Criar um modal com JavaScript ficou mais simples usando o elemento nativo dialog. Com poucos métodos, como showModal() e close(), é possível abrir e fechar janelas modais sem depender de bibliotecas externas.
Essa abordagem reduz código, melhora a manutenção e aproveita recursos nativos do navegador, como o bloqueio da interação com o restante da página e o uso do ::backdrop para estilizar o fundo do modal.