Quando um elemento <dialog> é aberto como um modal usando showModal(), o navegador o promove para a camada superior e marca o restante do documento como inerte. Embora isso bloqueie os cliques do ponteiro e o foco do teclado na página, não impede a rolagem:
- Rolar enquanto o ponteiro ou o gesto de toque está sobre o
::backdroprola a página abaixo. - A rolagem dentro do
<dialog>é encadeada à página de fundo quando a caixa de diálogo atinge o limite de rolagem ou imediatamente se o conteúdo da caixa de diálogo não transborda.
De acordo com a especificação do comportamento de rolagem esticada do CSS, overscroll-behavior se aplica a todos os elementos de contêiner de rolagem, incluindo contêineres de rolagem não roláveis (elementos com overflow: hidden ou overflow: auto cujo conteúdo não transborda no momento). Ao combinar overscroll-behavior: contain no <dialog> com overflow: hidden e overscroll-behavior: contain no dialog::backdrop, é possível impedir que a página de fundo seja rolada usando CSS puro.
Implementação
1. Contém encadeamento de rolagem no <dialog>
A folha de estilo do user agent define overflow: auto em <dialog>, tornando-o um contêiner de rolagem por padrão. Aplique overscroll-behavior: contain (ou none) a dialog:modal (ou dialog).
2. Transformar ::backdrop em um contêiner de rolagem e conter a rolagem dele
Por padrão, dialog::backdrop tem overflow: visible, o que significa que não é um contêiner de rolagem e ignora overscroll-behavior. É necessário definir overflow: hidden em dialog::backdrop para que ele seja um contêiner de rolagem não rolável e pareá-lo com overscroll-behavior: contain para que os gestos de rolagem realizados no plano de fundo sejam capturados e não alcancem o documento abaixo.
Exemplo de código
dialog:modal {
/* MANDATORY: Prevent scroll gestures inside the modal (even when its content
does not overflow) from chaining to the underlying page. */
overscroll-behavior: contain;
}
dialog::backdrop {
/* MANDATORY: ::backdrop defaults to overflow: visible (not a scroll container).
Set overflow: hidden so it becomes a non-scrollable scroll container that
honors overscroll-behavior. */
overflow: hidden;
overscroll-behavior: contain;
}
Práticas recomendadas e restrições
- OBRIGATÓRIO: defina
overscroll-behavior: containno próprio elemento<dialog>(usando o seletordialog:modal) e nodialog::backdrop. Sem essa declaração, os gestos de rolagem sobre o plano de fundo ou dentro da caixa de diálogo ainda vão ser encadeados à página. - OBRIGATÓRIO: defina
overflow: hidden(ouoverflow: auto) emdialog::backdroppara que ele se torne um contêiner de rolagem. Sem essa declaração,::backdropassume como padrãooverflow: visible, eoverscroll-behaviornão tem efeito. - NÃO use
overflow: clipouoverflow: visibleemdialog::backdropoudialog. Nenhum dos valores estabelece um contêiner de rolagem, entãooverscroll-behaviornão será aplicado. - NÃO aplique
overflow: hiddenouposition: fixeda<html>ou<body>para bloquear a rolagem em segundo plano quando uma caixa de diálogo for aberta. A mutação do overflow raiz remove a barra de rolagem da página (causando uma mudança de layout horizontal), pode redefinir ou pular a posição de rolagem da página e pode quebrar elementosposition: stickyna página em questão.
Estratégias de fallback
Embora a propriedade CSS overscroll-behavior seja compatível com todos os principais navegadores para contêineres de rolagem com conteúdo transbordante, respeitar overscroll-behavior em contêineres de rolagem não roláveis é uma especificação mais recente que não pode ser detectada por recursos.
NÃO tente detectar o suporte a contêineres não roláveis com @supports (overscroll-behavior: contain) ou CSS.supports('overscroll-behavior', 'contain'). Todos os navegadores mais recentes são compatíveis com a sintaxe da propriedade overscroll-behavior: contain e retornam true, mesmo que só a apliquem quando o conteúdo transborda.
Em vez disso, trate a contenção de rolagem em contêineres não roláveis como um aprimoramento progressivo:
- Em navegadores que oferecem suporte a
overscroll-behaviorem contêineres de rolagem não roláveis, a rolagem da página em segundo plano é totalmente impedida tanto emdialog::backdropquanto dentro de<dialog>(independentemente de o conteúdo transbordar ou não). - Em navegadores que ainda não oferecem suporte a
overscroll-behaviorem contêineres de rolagem não roláveis,overscroll-behavior: containemdialogainda impede o encadeamento de rolagem sempre que o conteúdo da caixa de diálogo transborda e é rolável. Enquanto isso,showModal()ainda captura o foco do teclado e marca o documento em segundo plano comoinert. - É recomendável usar o aprimoramento progressivo em vez de soluções legadas que aplicam
overflow: hiddenouposition: fixeda<html>ou<body>, porque ele não remove a barra de rolagem raiz, não causa mudanças de layout horizontal, não pula a posição de rolagem da página nem quebra elementosposition: stickyna página.