Prevent the Page Underneath a Modal Dialog from Scrolling

Quando un elemento <dialog> viene aperto come finestra modale utilizzando showModal(), il browser lo promuove al livello superiore e contrassegna il resto del documento come inerte. Sebbene questo blocchi i clic del puntatore e la selezione della tastiera sulla pagina sottostante, non impedisce lo scorrimento:

  1. Lo scorrimento mentre il puntatore o il gesto di tocco si trova sopra ::backdrop fa scorrere la pagina sottostante.
  2. Lo scorrimento all'interno di <dialog> si collega alla pagina sottostante una volta che la finestra di dialogo raggiunge il limite di scorrimento o immediatamente se i contenuti della finestra di dialogo non presentano overflow.

In base alla specifica CSS Overscroll Behavior, overscroll-behavior si applica a tutti gli elementi contenitore di scorrimento, inclusi i contenitori di scorrimento non scorrevoli (elementi con overflow: hidden o overflow: auto i cui contenuti non presentano attualmente overflow). Combinando overscroll-behavior: contain su <dialog> con overflow: hidden e overscroll-behavior: contain su dialog::backdrop, puoi impedire lo scorrimento della pagina sottostante utilizzando solo CSS.

Implementazione

1. Contenere il concatenamento dello scorrimento su <dialog>

Il foglio di stile dello user agent imposta overflow: auto su <dialog>, rendendolo un contenitore di scorrimento per impostazione predefinita. Applica overscroll-behavior: contain (o none) a dialog:modal (o dialog).

2. Trasforma ::backdrop in un container di scorrimento e limita lo scorrimento

Per impostazione predefinita, dialog::backdrop ha overflow: visible, il che significa che non è un container di scorrimento e ignora overscroll-behavior. Devi impostare overflow: hidden su dialog::backdrop per renderlo un contenitore di scorrimento non scorrevole e associarlo a overscroll-behavior: contain in modo che i gesti di scorrimento eseguiti sullo sfondo vengano intercettati e non raggiungano il documento sottostante.

Codice di esempio

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;
}

Best practice e vincoli

  • OBBLIGATORIO: imposta overscroll-behavior: contain sull'elemento <dialog> stesso (utilizzando il selettore dialog:modal) e su dialog::backdrop. Senza questa dichiarazione, i gesti di scorrimento sullo sfondo o all'interno della finestra di dialogo verranno comunque concatenati alla pagina.
  • OBBLIGATORIO: imposta overflow: hidden (o overflow: auto) su dialog::backdrop in modo che diventi un contenitore di scorrimento. Senza questa dichiarazione, ::backdrop viene impostato su overflow: visible per impostazione predefinita e overscroll-behavior non avrà alcun effetto.
  • NON utilizzare overflow: clip o overflow: visible su dialog::backdrop o dialog. Nessuno dei due valori stabilisce un container di scorrimento, quindi overscroll-behavior non verrà applicato.
  • NON applicare overflow: hidden o position: fixed a <html> o <body> per bloccare lo scorrimento in background quando si apre una finestra di dialogo. La modifica dell'overflow della radice rimuove la barra di scorrimento della pagina (causando una variazione del layout orizzontale), può reimpostare o saltare la posizione di scorrimento della pagina e può interrompere gli elementi position: sticky nella pagina sottostante.

Strategie di fallback

Sebbene la proprietà CSS overscroll-behavior sia supportata da tutti i principali browser per i contenitori di scorrimento con contenuti in overflow, il rispetto di overscroll-behavior sui contenitori di scorrimento non scorrevoli è una specifica più recente che non può essere rilevata dalle funzionalità.

NON tentare di rilevare le funzionalità di supporto dei container non scorrevoli con @supports (overscroll-behavior: contain) o CSS.supports('overscroll-behavior', 'contain'). Tutti i browser moderni supportano la sintassi della proprietà overscroll-behavior: contain e restituiscono true, anche se la applicano solo quando i contenuti superano i limiti.

Considera invece il contenimento dello scorrimento nei contenitori di scorrimento non scorrevoli come un potenziamento progressivo:

  • Nei browser che supportano overscroll-behavior su contenitori di scorrimento non scorrevoli, lo scorrimento della pagina in background è completamente impedito sia su dialog::backdrop che all'interno di <dialog> (indipendentemente dal fatto che i contenuti siano in overflow o meno).
  • Nei browser che non supportano ancora overscroll-behavior su contenitori di scorrimento non scorrevoli, overscroll-behavior: contain su dialog impedisce comunque il concatenamento dello scorrimento ogni volta che i contenuti della finestra di dialogo superano il limite e sono scorrevoli. Nel frattempo, showModal() continua a bloccare la selezione della tastiera e contrassegna il documento in background inert.
  • È consigliabile fare affidamento sul potenziamento progressivo anziché su soluzioni alternative legacy che applicano overflow: hidden o position: fixed a <html> o <body>, perché non rimuovono la barra di scorrimento principale, non causano variazioni del layout orizzontale, non saltano la posizione di scorrimento della pagina e non interrompono gli elementi position: sticky nella pagina sottostante.