Tag HTML <dialog>
Aprenda a tag HTML <dialog>: show() vs showModal(), o padrão form method="dialog", eventos close e cancel, e acessibilidade.
A tag <dialog> é um dos elementos HTML5. Ela cria uma caixa de diálogo nativa — um painel pop-up como uma mensagem de confirmação, um alerta ou um formulário — com o qual o usuário interage antes de continuar. O dialog fica oculto por padrão e é exibido e ocultado por meio de uma pequena API JavaScript.
Esta página aborda as duas formas de abrir um dialog (show() e showModal()), como fechá-lo e ler seu resultado, o padrão <form method="dialog">, os eventos close e cancel, acessibilidade e como estilizar o backdrop.
Por que usar o <dialog> nativo em vez de um modal com <div> personalizado?
Antes do <dialog>, os desenvolvedores construíam modais manualmente com um <div> mais um conjunto de CSS e JavaScript. O elemento nativo faz esse trabalho por você e de forma mais confiável:
- Aprisionamento de foco integrado. Quando aberto com
showModal(), o foco do teclado (Tab / Shift+Tab) fica mantido dentro do dialog. Um modal com<div>precisa aprisionar o foco manualmente, e errar nisso é um bug de acessibilidade comum. - Empilhamento na camada superior. Um dialog modal é renderizado na camada superior do navegador, portanto sempre aparece acima do restante da página, independentemente do
z-index. Chega de guerras dez-index. - Backdrop automático.
showModal()desenha um pseudo-elemento::backdropatrás do dialog que bloqueia cliques na página abaixo — nenhum elemento de sobreposição extra é necessário. - Fechar com Escape. Pressionar Esc fecha um dialog modal automaticamente (disparando um evento
cancelao qual você pode reagir). - Semântica real. O elemento possui um
role="dialog"implícito, portanto as tecnologias assistivas o anunciam corretamente sem ARIA extra.
Sintaxe
A tag <dialog> vem em pares. Coloque o conteúdo do dialog entre as tags de abertura (<dialog>) e de fechamento (</dialog>). Você o abre via script com um dos dois métodos no objeto DOM do elemento:
dialog.show()— abre um dialog não modal.dialog.showModal()— abre um dialog modal.dialog.close([returnValue])— fecha o dialog e, opcionalmente, registra um valor de retorno.
O atributo boolean open reflete se o dialog está sendo exibido no momento. Geralmente você não o define manualmente; os métodos acima cuidam disso para você.
Dialogs não modais: show()
show() abre o dialog no lugar, sem bloquear a página. O restante do documento permanece interativo, não há ::backdrop, o foco não é aprisionado e Esc não o fecha. Esta é a escolha certa para painéis dispensáveis e não críticos, como uma pequena caixa de ferramentas, uma nota de "novidades" ou um seletor inline.
<!DOCTYPE html>
<html>
<head>
<title>Non-modal dialog with show()</title>
</head>
<body>
<button id="open">Open non-modal dialog</button>
<dialog id="info">
<p>You can still click and scroll the page behind me.</p>
<button id="close">Close</button>
</dialog>
<script>
const dialog = document.getElementById("info");
document.getElementById("open").addEventListener("click", () => {
dialog.show();
});
document.getElementById("close").addEventListener("click", () => {
dialog.close();
});
</script>
</body>
</html>Dialogs modais: showModal()
showModal() abre o dialog como um modal. Isso altera o comportamento de quatro maneiras importantes:
- A interação é bloqueada. Tudo fora do dialog torna-se inerte — cliques e entradas de teclado não conseguem alcançar a página atrás dele.
- Um backdrop aparece. O navegador renderiza o pseudo-elemento
::backdropatrás do dialog, que você pode estilizar. - O foco é aprisionado. A navegação por Tab percorre apenas os elementos focalizáveis dentro do dialog.
- Ele entra na camada superior. O dialog é renderizado acima de todo o conteúdo, ignorando o
z-index. Pressionar Esc o fecha.
<!DOCTYPE html>
<html>
<head>
<title>Modal dialog with showModal()</title>
<style>
dialog {
width: 40%;
border: 1px solid #ccc;
border-radius: 0.5em;
padding: 1em;
}
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<button id="open">Open modal dialog</button>
<dialog id="confirm">
<p>The page behind is blocked. Press Esc or a button to close.</p>
<button id="close">Close dialog</button>
</dialog>
<script>
const dialog = document.getElementById("confirm");
document.getElementById("open").addEventListener("click", () => {
dialog.showModal();
});
document.getElementById("close").addEventListener("click", () => {
dialog.close();
});
</script>
</body>
</html>O padrão <form method="dialog">
Um <form> dentro de um <dialog> pode usar method="dialog". Enviar esse formulário fecha o dialog sem enviar uma requisição de rede, e o valor do <button> de envio que foi clicado é armazenado na propriedade DOM returnValue do dialog. Isso facilita identificar qual botão o usuário escolheu.
<!DOCTYPE html>
<html>
<head>
<title>Dialog with a form</title>
</head>
<body>
<button id="open">Delete file</button>
<p id="result"></p>
<dialog id="confirm">
<form method="dialog">
<p>Are you sure you want to delete this file?</p>
<button value="cancel">Cancel</button>
<button value="delete">Delete</button>
</form>
</dialog>
<script>
const dialog = document.getElementById("confirm");
const result = document.getElementById("result");
document.getElementById("open").addEventListener("click", () => {
dialog.showModal();
});
dialog.addEventListener("close", () => {
// returnValue is the value of the button that submitted the form
result.textContent = "You chose: " + dialog.returnValue;
});
</script>
</body>
</html>returnValue é uma propriedade do elemento DOM, não um atributo HTML — você a lê ou define via JavaScript. Também é possível defini-la diretamente ao fechar por código: dialog.close("delete").
Os eventos close e cancel
Um <dialog> dispara dois eventos que você pode ouvir:
| Evento | Quando é disparado |
|---|---|
close | Sempre que o dialog é fechado — por close(), pelo envio de um formulário method="dialog", ou por Esc. Leia returnValue aqui. |
cancel | Quando o usuário dispensa um dialog modal com a tecla Esc. Disparado antes de close. Chame event.preventDefault() para manter o dialog aberto. |
<dialog id="editor">
<p>Unsaved changes — Esc would normally close me.</p>
<button onclick="this.closest('dialog').close()">Done</button>
</dialog>
<script>
const dialog = document.getElementById("editor");
dialog.addEventListener("cancel", (event) => {
// Prevent Esc from discarding unsaved work
event.preventDefault();
});
dialog.addEventListener("close", () => {
console.log("Dialog closed");
});
</script>Para saber mais sobre como conectar esses listeners, consulte Eventos JavaScript e o HTML DOM do JavaScript.
Acessibilidade
Um <dialog> tem um role="dialog" implícito, mas você ainda precisa fornecer um nome acessível e gerenciar o foco:
- Nomeie o dialog. Aponte
aria-labelledbypara o id do cabeçalho do dialog para que os leitores de tela anunciem seu título. Usearia-describedbypara uma descrição mais longa. - Foco ao abrir.
showModal()move o foco para dentro do dialog automaticamente — para o primeiro elemento focalizável, ou para um elemento marcado com o atributoautofocus. Prefira colocarautofocusem um controle seguro (como Cancelar) em vez de um destrutivo. - Retornar o foco ao fechar. Quando o dialog fecha, retorne o foco ao controle que o abriu para que os usuários de teclado não fiquem no topo da página. Com o
<dialog>nativo, o navegador faz isso por você; para os resultados mais seguros, armazene e restaure o gatilho você mesmo.
<button id="open">Edit profile</button>
<dialog id="profile" aria-labelledby="profile-title" aria-describedby="profile-desc">
<h2 id="profile-title">Edit profile</h2>
<p id="profile-desc">Update your display name, then save.</p>
<form method="dialog">
<input type="text" aria-label="Display name" autofocus>
<button value="save">Save</button>
</form>
</dialog>
<script>
const openButton = document.getElementById("open");
const dialog = document.getElementById("profile");
openButton.addEventListener("click", () => dialog.showModal());
// Explicitly return focus to the trigger when the dialog closes
dialog.addEventListener("close", () => openButton.focus());
</script>Veja Considerações de acessibilidade no DOM para saber mais sobre como criar widgets interativos acessíveis.
Estilizando o dialog e seu backdrop
Você pode estilizar a caixa de dialog em si e, para dialogs modais, a área atrás dela com o pseudo-elemento ::backdrop.
dialog {
border: 1px solid #ccc;
border-radius: 0.5em;
padding: 1em;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}
/* Only rendered for dialogs opened with showModal() */
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}Atributos
| Atributo | Valor | Descrição |
|---|---|---|
open | open | Atributo boolean que indica que o dialog está sendo exibido no momento. Geralmente definido para você por show() / showModal(). |
A tag <dialog> também suporta os Atributos Globais e os Atributos de Evento.