HTML Dialog

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>

Javascript

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

CSS

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;
  }
}

Voilà ✨

Sua modal deve estar assim