Sobreposições e feedback de estado

Caixa de diálogo modal

Use o elemento dialog nativo para implementar uma caixa de diálogo de confirmação acessível.

HTMLCSSJavaScriptDialog
É possível editar, executar e salvar este exemplo após ativar JavaScript. O código-fonte fixo é o seguinte:
<!doctype html>
<html lang="pt-BR" dir="ltr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Caixa de diálogo modal</title>
  <style>
    * { box-sizing: border-box; }
    body {
      min-height: 100vh;
      margin: 0;
      display: grid;
      place-items: center;
      padding: 24px;
      color: #2a241f;
      font-family: "Avenir Next", "Microsoft YaHei", sans-serif;
      background: #efe9df;
      background-image: radial-gradient(#c7baaa 1px, transparent 1px);
      background-size: 22px 22px;
    }
    .card {
      width: min(680px, 100%);
      padding: clamp(28px, 6vw, 58px);
      border: 1px solid #d8cbbb;
      border-radius: 4px 38px 4px 38px;
      background: #fffdf8;
      box-shadow: 16px 18px 0 #d8cbbb;
    }
    .number { display: block; color: #9a4c33; font: 700 13px/1 Georgia, serif; letter-spacing: .18em; }
    h1 { max-width: 520px; margin: 16px 0 12px; font: 700 clamp(38px, 8vw, 68px)/.98 Georgia, "STSong", serif; }
    .card p { max-width: 520px; margin: 0 0 30px; color: #6f6359; line-height: 1.75; }
    button { border: 0; font: inherit; font-weight: 750; cursor: pointer; }
    .open-button { padding: 14px 22px; border-radius: 999px; color: #fffdf8; background: #2a241f; box-shadow: 0 8px 0 #9a4c33; transition: transform .15s ease, box-shadow .15s ease; }
    .open-button:active { transform: translateY(5px); box-shadow: 0 3px 0 #9a4c33; }
    button:focus-visible { outline: 3px solid #d27853; outline-offset: 3px; }
    dialog {
      width: min(470px, calc(100% - 32px));
      padding: 0;
      border: 0;
      border-radius: 28px;
      color: #2a241f;
      background: #fffdf8;
      box-shadow: 0 24px 90px rgba(33, 24, 19, .35);
    }
    dialog::backdrop { background: rgba(35, 27, 21, .68); backdrop-filter: blur(5px); }
    dialog[open] { animation: rise .28s ease both; }
    .dialog-body { padding: 34px; }
    .icon { display: grid; width: 54px; height: 54px; place-items: center; border-radius: 50%; color: #9a4c33; font-size: 25px; background: #f6dfd5; }
    h2 { margin: 20px 0 8px; font: 700 30px/1.15 Georgia, "STSong", serif; }
    .dialog-body p { margin: 0; color: #706258; line-height: 1.65; }
    .actions { display: flex; justify-content: flex-end; gap: 12px; padding: 18px 34px 28px; }
    .actions button { padding: 12px 18px; border-radius: 999px; }
    .cancel { color: #4f443c; background: #eee8df; }
    .confirm { color: white; background: #9a4c33; }
    .status { min-height: 24px; margin-top: 24px !important; color: #9a4c33 !important; font-weight: 700; }
    @keyframes rise { from { opacity: 0; transform: translateY(24px) scale(.96); } }
    @media (prefers-reduced-motion: reduce) { dialog[open] { animation: none; } }
  </style>
</head>
<body>
  <main class="card">
    <span class="number">COMPONENT 02</span>
    <h1>Uma confirmação clara</h1>
    <p>O dialog nativo gerencia automaticamente o foco e a interação com o fundo. Clique no botão para ver o fluxo de confirmação ou pressione Esc para fechar.</p>
    <button id="openDialog" class="open-button" type="button">Abrir diálogo</button>
    <p id="status" class="status" role="status" aria-live="polite"></p>
  </main>

  <dialog id="confirmDialog" aria-labelledby="dialogTitle" aria-describedby="dialogDescription">
    <div class="dialog-body">
      <div class="icon" aria-hidden="true">✓</div>
      <h2 id="dialogTitle">Confirmar o salvamento deste design?</h2>
      <p id="dialogDescription">Depois de salvar, a nova versão substituirá o rascunho atual. Você ainda pode recuperar a versão antiga no histórico.</p>
    </div>
    <div class="actions">
      <button class="cancel" type="button" data-dialog-result="cancel">Não salvar por enquanto</button>
      <button class="confirm" type="button" data-dialog-result="confirm">Salvar confirmações</button>
    </div>
  </dialog>

  <script>
    const dialog = document.querySelector('#confirmDialog');
    const status = document.querySelector('#status');
    document.querySelector('#openDialog').addEventListener('click', () => {
      dialog.returnValue = '';
      dialog.showModal();
    });
    document.querySelectorAll('[data-dialog-result]').forEach(button => {
      button.addEventListener('click', () => dialog.close(button.dataset.dialogResult));
    });
    dialog.addEventListener('close', () => {
      status.textContent = dialog.returnValue === 'confirm' ? 'O design foi salvo com segurança.' : 'A operação foi cancelada e nenhum conteúdo foi alterado.';
    });
  </script>
</body>
</html>
Feedback da páginaEncontrou um problema ou tem uma sugestão de melhoria?
Recursos de feedback precisam ser usados na versão online

Envie somente após ativar JavaScript na versão online; a funcionalidade local da ferramenta ou do exemplo não é afetada.

Ir para o feedback na versão online