W3docs

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 de z-index.
  • Backdrop automático. showModal() desenha um pseudo-elemento ::backdrop atrá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 cancel ao 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:

  1. 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.
  2. Um backdrop aparece. O navegador renderiza o pseudo-elemento ::backdrop atrás do dialog, que você pode estilizar.
  3. O foco é aprisionado. A navegação por Tab percorre apenas os elementos focalizáveis dentro do dialog.
  4. 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>
Result

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:

EventoQuando é disparado
closeSempre que o dialog é fechado — por close(), pelo envio de um formulário method="dialog", ou por Esc. Leia returnValue aqui.
cancelQuando 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-labelledby para o id do cabeçalho do dialog para que os leitores de tela anunciem seu título. Use aria-describedby para 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 atributo autofocus. Prefira colocar autofocus em 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

AtributoValorDescrição
openopenAtributo 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.

Prática

Prática
Quais afirmações sobre o elemento HTML <dialog> estão corretas?
Quais afirmações sobre o elemento HTML <dialog> estão corretas?
Was this page helpful?