As caixas de diálogo modais modernas geralmente oferecem suporte ao "fechamento rápido", permitindo que os usuários fechem uma caixa de diálogo clicando ou tocando no plano de fundo (a área fora da caixa de diálogo). O atributo closedby oferece uma maneira declarativa de ativar esse comportamento sem JavaScript personalizado.
Implementação
Para ativar a dispensa leve:
- Adicione
closedby="any"ao elemento<dialog>. - Abra a caixa de diálogo usando
dialog.showModal().
Valores de atributo
any: ativa o fechamento rápido (clicar no plano de fundo), as "solicitações de fechamento" (a teclaEsc) e os mecanismos para desenvolvedores (por exemplo,dialog.close()).closerequest: ativa apenas as "solicitações de fechamento" e os mecanismos para desenvolvedores. Esse é o padrão para caixas de diálogo modais.none: somente os mecanismos do desenvolvedor podem fechar a caixa de diálogo.
Como estilizar o pano de fundo
Quando uma caixa de diálogo é aberta como um modal usando showModal(), o navegador gera um pseudoelemento ::backdrop. Esse plano de fundo cobre toda a janela de visualização e fica diretamente atrás da caixa de diálogo.
/* Style the backdrop to indicate the dialog is modal */
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(2px); /* Optional: add blur for modern browsers */
}
Exemplo
<!-- MANDATORY: Use closedby="any" to enable light-dismiss behavior -->
<dialog id="myDialog" closedby="any" aria-labelledby="dialogTitle">
<form method="dialog">
<h2 id="dialogTitle">Feedback</h2>
<p>Click outside this box or press Esc to dismiss.</p>
<button type="submit">Close</button>
</form>
</dialog>
<button onclick="document.getElementById('myDialog').showModal()">Open Dialog</button>
Restrições e acessibilidade
- OBRIGATÓRIO: use
closedby="any"para ativar a dispensa leve de forma declarativa. - OBRIGATÓRIO: sempre abra caixas de diálogo modais com
showModal(). Isso garante que a caixa de diálogo esteja na camada superior, que o foco seja mantido e que a teclaEscseja processada. - RECOMENDADO: use
aria-labelledbyouaria-labelpara fornecer um nome acessível para a caixa de diálogo. - NÃO: use
closedbypara caixas de diálogo não modais (abertas comshow()), porque elas não têm um plano de fundo e não acionam o fechamento ao tocar fora. - NÃO: use o evento
clickpara uma lógica crítica que precisa acontecer antes do fechamento. Em vez disso, detecte os eventoscloseoucancel.
Estratégias de fallback
OBRIGATÓRIO: para navegadores que ainda não oferecem suporte a closedby, você precisa implementar um substituto para o fechamento leve, verificando se um clique ocorreu fora dos limites do conteúdo da caixa de diálogo usando o seguinte script:
const dialog = document.querySelector('dialog');
// Fallback for browsers without closedby support
if (!('closedBy' in HTMLDialogElement.prototype)) {
dialog.addEventListener('click', (event) => {
// 1. When clicking the backdrop, the event target is the dialog element itself.
// Ignore clicks where the target is a child element inside the dialog.
if (event.target !== dialog) return;
// 2. Check if the click coordinates fall within the dialog's content box.
// This distinguishes between a click on the backdrop vs a click on the dialog's background/padding.
const rect = dialog.getBoundingClientRect();
const isDialogContent = (
rect.top <= event.clientY &&
event.clientY <= rect.top + rect.height &&
rect.left <= event.clientX &&
event.clientX <= rect.left + rect.width
);
if (isDialogContent) return;
// 3. Since the click was outside the content area (on the backdrop), manually close the dialog.
dialog.close();
});
}