Uma vez, precisei implementar uma modal em um sistema construído com WebObjects, sem React ou qualquer outra biblioteca moderna, a maioria do front-end era feito apenas com HTML, CSS e JavaScript puro
Então foi ai que eu encontrei a tag <dialog/>
do HTML, desde então, venho pensando em compartilhar essa alternativa pouco conhecida, mas extremamente útil
Primeiro eu criei o HTML básico da modal, que é bem simples:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
<title>Dialog</title>
</head>
<body>
<dialog id="dialog" class="dialog">
<header>
<button id="close-dialog">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-x-icon lucide-x">
<path d="M18 6 6 18"></path>
<path d="m6 6 12 12"></path>
</svg>
</button>
<h3>Convide um amigo!</h3>
<p>
Indique um amigo e ganhe! Digite o email dele abaixo para enviarmos um
convite especial com vantagens para ambos. 🎉
</p>
</header>
<form>
<input type="email" placeholder="ex. person@gmail.com" />
<div>
<button>Convidar</button>
<p>O e-mail pode levar até 5 minutos para chegar</p>
</div>
</form>
</dialog>
<!-- Botão para abrir a modal -->
<div class="container">
<button id="open-dialog">Abrir modal de convite</button>
</div>
</body>
</html>
Para o botão de sair da modal eu estou usando uma imagem com o SVG do "X" do lucide.dev, mas a escolha do elemento é totalmente pessoal, você pode substituir por outro ícone, um texto como "Fechar" — qualquer conteúdo clicável funciona, desde que chame o .close() do <dialog>
Com o HTML pronto, eu fui para o Javascript, para testar o comportamento da modal
const dialog = document.getElementById("dialog");
const openDialogButton = document.getElementById("open-dialog");
const closeDialogButton = document.getElementById("close-dialog");
openDialogButton.addEventListener("click", () => {
dialog.showModal();
});
closeDialogButton.addEventListener("click", () => {
dialog.close();
});
Basicamente eu estou pegando o elemento da modal e os botões de abrir e fechar, e adicionando um evento de click para abrir e fechar a modal
A própria tag oferece métodos nativos: o showModal()
exibe a modal no centro da tela com um backdrop (o fundo escuro), enquanto o close()
faz ela fechar
Agora que o HTML e o Javascript estão prontos, eu fui para o CSS que foi sem dúvida fez e faz toda a diferença 😁
🚨 Nested CSS abaixo
body {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Geist", sans-serif;
background-color: #f1f1f1;
}
#dialog {
border: none;
border-radius: 8px;
max-width: 400px;
padding: 2rem;
}
header {
/* 👇 aqui eu setei relative para posicionar o botão no canto superior esquerdo */
position: relative;
text-align: center;
& > img {
position: absolute;
}
& h3 {
font-family: "Poppins", sans-serif;
margin-top: 0.2rem;
letter-spacing: -0.025em;
color: #000;
}
& button {
background-color: transparent;
border: none;
color: #333;
position: absolute;
top: 0;
right: 0;
display: flex;
font-size: 1.5em;
cursor: pointer;
transition: opacity 0.3s;
&:hover {
opacity: 0.6;
}
}
& p {
font-size: 0.8em;
}
}
form {
margin-top: 1.2rem;
position: relative;
display: flex;
flex-direction: column;
gap: 1rem;
& p {
font-size: 0.7em;
color: #71717a;
margin: 0;
margin-top: 10px;
text-align: center;
}
& button {
width: 100%;
background-color: #000;
border: none;
color: white;
padding: 10px 20px;
font-weight: bold;
display: flex;
justify-content: center;
align-items: center;
gap: 0.1rem;
cursor: pointer;
border-radius: 8px;
transition: background-color 0.3s;
font-family: "Geist", sans-serif;
&:hover {
opacity: 0.9;
}
& img {
height: 1rem;
}
}
& input {
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 5px;
}
}
.container {
height: 100svh;
display: flex;
justify-content: center;
align-items: center;
& > button {
padding: 10px 20px;
background-color: #000;
color: #fff;
border: none;
border-radius: 8px;
font-weight: bold;
cursor: pointer;
}
}
Sua modal deve estar assim