SW Core
SW Core / CSS / Modal nativo (sw-dialog)

Modal nativo (sw-dialog) CSS

A janela de confirmação do próprio navegador, com entrada e saída animadas, fundo desfocado e a página travada atrás. Abrir é uma linha.

O que é

É a janelinha que aparece no meio da tela pedindo uma resposta: "Confirmar agendamento?", "Excluir este produto?", "Preencha seus dados". O HTML já tem uma peça para isso, o <dialog>: ele prende o foco dentro, fecha com Esc e avisa o leitor de tela. O sw-dialog dá o visual do SW Core, a animação de entrada e saída, escurece e desfoca o fundo e trava a rolagem da página enquanto está aberto. Tem dois formatos: central (padrão) e lateral (gaveta entrando pela direita).

Para abrir, uma linha de JavaScript: document.getElementById('id').showModal(). Para fechar, nenhuma: qualquer botão dentro de um <form method="dialog"> fecha o modal, e o value desse botão fica guardado em returnValue (assim você sabe se a pessoa clicou em "Confirmar" ou "Voltar"). É a opção leve para sites; o sw-modal continua existindo para os sistemas que já usam.

Quando usar

  • Confirmar uma ação (agendar, excluir, cancelar pedido): sw-dialog central com dois botões.
  • Formulário curto sem sair da página (orçamento, newsletter, login): sw-dialog com o formulário dentro.
  • Carrinho, detalhes, menu no celular: gaveta sw-dialog="lateral".
  • Aviso que não precisa de resposta ("Salvo!")? Use o sw-popover "toast", que não trava a página.

Comece aqui

  1. 1

    Coloque o SW Core no <head>. O sw-dialog está no arquivo principal.

    <link rel="stylesheet" href="swcore/swcore.min.css">
  2. 2

    Escreva o <dialog sw-dialog> com um id, um botão que chama showModal() e, dentro, um <form method="dialog"> com o botão de fechar. Clique para abrir; feche pelo botão ou com Esc.

    Horário reservado!

    Terça, 14h — Corte + barba. Enviamos a confirmação no seu WhatsApp.

    <button sw-btn="pri" onclick="document.getElementById('reserva').showModal()">Agendar horário</button>
    
    <dialog id="reserva" sw-dialog>
      <h3 class="mt-0">Horário reservado!</h3>
      <p>Terça, 14h — Corte + barba. Enviamos a confirmação no seu WhatsApp.</p>
      <form method="dialog"><button sw-btn="pri">Fechar</button></form>
    </dialog>

Todas as variações

Cada quadro abaixo é o componente de verdade, rodando. O código embaixo é exatamente o que está no quadro: copie e cole.

1. Formatos

Clique nos botões. O modal sai do quadro e abre por cima da página inteira.

Confirmar agendamento?

Terça, 14h — Corte + barba.

sw-dialog — central (padrão) <button sw-btn="pri" onclick="document.getElementById('confirma').showModal()">Abrir central</button> <dialog id="confirma" sw-dialog> <h3 class="mt-0">Confirmar agendamento?</h3> <p>Terça, 14h — Corte + barba.</p> <form method="dialog" class="flx gap-2"> <button sw-btn="pri" value="sim">Confirmar</button> <button sw-btn="ghost" value="nao">Voltar</button> </form> </dialog>

Detalhes do pedido

Pedido #1041 — 2 itens — R$ 388,00

Entrega prevista: sexta-feira.

sw-dialog="lateral" — gaveta pela direita <button sw-btn="pri out" onclick="document.getElementById('pedido').showModal()">Abrir lateral</button> <dialog id="pedido" sw-dialog="lateral"> <h3 class="mt-0">Detalhes do pedido</h3> <p>Pedido #1041 — 2 itens — R$ 388,00</p> <p class="t-mut">Entrega prevista: sexta-feira.</p> <form method="dialog"><button sw-btn="pri">Fechar</button></form> </dialog>

2. Saber o que a pessoa escolheu

O value do botão que fechou fica em returnValue. O evento close avisa quando fechou. Abra, escolha e veja a resposta embaixo do botão.

Nenhuma escolha ainda.

Excluir "Sapato social"?

Essa ação não pode ser desfeita.

value nos botões + evento close <button sw-btn="err" id="btn-excluir"><i class="swi-trash"></i> Excluir produto</button> <dialog id="excluir" sw-dialog> <h3 class="mt-0">Excluir "Sapato social"?</h3> <p>Essa ação não pode ser desfeita.</p> <form method="dialog" class="flx gap-2"> <button sw-btn="err" value="excluir">Excluir de vez</button> <button sw-btn="ghost" value="manter">Manter</button> </form> </dialog> <script> const dlg = document.getElementById('excluir'); document.getElementById('btn-excluir').onclick = () => { dlg.returnValue = ''; // zera a resposta anterior dlg.showModal(); }; dlg.addEventListener('close', () => { if (dlg.returnValue === 'excluir') { /* apague o produto aqui */ } }); </script>

Tabela de opções

PalavraO que fazExemplo
No <dialog> — formato (sw-dialog)
(nenhum)Central, até 52rem de largura, com fundo escurecido e desfocado.<dialog sw-dialog>
lateralGaveta na direita, altura total da tela, entrando de lado.<dialog sw-dialog="lateral">
Para fechar (do HTML)
<form method="dialog">Qualquer botão dentro deste formulário fecha o modal. Não precisa de JavaScript.<form method="dialog">…</form>
value (no botão)O que fica guardado em returnValue quando esse botão fecha o modal.<button value="sim">
Tecla EscFecha sempre. O returnValue não muda (continua com o valor da vez anterior) — por isso zere ele antes de abrir.dialog.returnValue = ''
O que já vem pronto
FundoEscurecido e desfocado atrás do modal.
RolagemA página de trás fica travada enquanto o modal está aberto.
FocoO teclado fica preso dentro do modal; ao fechar, volta para o botão que abriu.

Receitas prontas — usos reais

Situações que aparecem em quase todo site. Copie a que servir.

Formulário de orçamento sem sair da página Ao vivo

Peça seu orçamento

<button sw-btn="suc g" onclick="document.getElementById('orcamento').showModal()">Pedir orçamento</button>

<dialog id="orcamento" sw-dialog>
  <h3 class="mt-0">Peça seu orçamento</h3>
  <form method="dialog" class="flx f-cl gap-3">
    <div sw-fld><label for="nome">Nome</label><input id="nome" sw-inp placeholder="Seu nome"></div>
    <div sw-fld><label for="zap">WhatsApp</label><input id="zap" sw-inp placeholder="(11) 99999-9999"></div>
    <div class="flx gap-2">
      <button sw-btn="suc" value="enviar">Enviar</button>
      <button sw-btn="ghost" value="cancelar">Cancelar</button>
    </div>
  </form>
</dialog>
<!-- para enviar de verdade ao servidor, troque method="dialog" pelo seu
     envio (action/AJAX) e feche com document.getElementById('orcamento').close() -->
Carrinho em gaveta lateral Ao vivo

Seu carrinho

Sapato socialR$ 239,00

Kit viagemR$ 149,00

TotalR$ 388,00

Finalizar
<button sw-btn="pri" onclick="document.getElementById('carrinho').showModal()"><i class="swi-cart"></i> Carrinho (2)</button>

<dialog id="carrinho" sw-dialog="lateral">
  <h3 class="mt-0">Seu carrinho</h3>
  <p class="flx j-sb"><span>Sapato social</span><strong>R$ 239,00</strong></p>
  <p class="flx j-sb"><span>Kit viagem</span><strong>R$ 149,00</strong></p>
  <p class="flx j-sb bd-t bd-mut pt-3"><span>Total</span><strong>R$ 388,00</strong></p>
  <form method="dialog" class="flx gap-2">
    <button sw-btn="ghost">Continuar comprando</button>
    <a href="/checkout" sw-btn="suc">Finalizar</a>
  </form>
</dialog>
Fechar também ao clicar fora (no fundo escuro) Ao vivo
Cachoeira

Clique no fundo escuro para fechar.

<button sw-btn="sec" onclick="document.getElementById('foto').showModal()">Ver foto ampliada</button>
<dialog id="foto" sw-dialog>
  <div class="ar-4-3 r-m ov-hi"><img src="/cachoeira.jpg" alt="Cachoeira" class="media-fill"></div>
  <p class="m-0 mt-2 t-mut t-p">Clique no fundo escuro para fechar.</p>
</dialog>

<script>
  // o clique no fundo escuro chega no próprio <dialog>, FORA da caixa dele
  const foto = document.getElementById('foto');
  foto.addEventListener('click', (e) => {
    const r = foto.getBoundingClientRect();
    const fora = e.clientX < r.left || e.clientX > r.right || e.clientY < r.top || e.clientY > r.bottom;
    if (fora) foto.close();
  });
</script>

Eventos

close
Do navegador, no <dialog>: dispara quando fecha (por botão, Esc ou close()). Leia dialog.returnValue para saber qual botão fechou.
cancel
Do navegador: dispara quando a pessoa aperta Esc, antes de fechar. event.preventDefault() impede o fechamento.

API (JavaScript)

dialog.showModal()
Abre como modal (fundo escuro, página travada, foco preso dentro).
dialog.close(valor?)
Fecha. O valor opcional vira o returnValue.
dialog.returnValue
O value do botão que fechou (ou o passado em close()).
dialog.open
true se está aberto.

Precisa de quê

  • swcore.min.css (2.1.0 ou mais novo) — visual, animação, fundo e trava da rolagem.
  • swcore.compl.min.css — só se usar os ícones swi-* dentro.
  • O <dialog> é do navegador (Chrome, Edge, Firefox e Safari atuais). A animação só aparece nos que já suportam; nos outros abre sem animar.

Cuidados — erros comuns

  • Use showModal(), não show(): o show() abre sem fundo, sem travar a página e sem prender o foco.
  • Não escreva <dialog open> no HTML para "já abrir": assim ele abre como caixa comum, não como modal. Para abrir ao carregar, chame showModal() no seu script.
  • O botão de fechar precisa estar dentro do <form method="dialog">. Botão fora do form não fecha.
  • Um <form method="dialog"> não envia nada ao servidor — ele só fecha. Para enviar de verdade, use o seu envio (AJAX ou action) e feche com close().
  • Clicar no fundo escuro não fecha por padrão (é do navegador). Se quiser, use o script da receita "Fechar também ao clicar fora".
  • Cada modal precisa de um id único na página.

O que ele não faz

  • A gaveta lateral sai só pela direita.
  • Um tamanho só para o central (até 52rem de largura, 90% da altura). Não há classes de tamanho.
  • Nos sistemas que já usam o sw-modal (com JS, tamanhos e API própria), continue com ele — o sw-dialog não o substitui.