Voorkomen dat de pagina onder een modaal dialoogvenster scrollt

Als een <dialog>-element wordt geopend als een modaal element met showModal(), plaatst de browser het in de bovenste laag en markeert de rest van het document als inert. Hoewel dit muisklikken en toetsenbordfocus op de onderliggende pagina blokkeert, voorkomt het niet dat er wordt gescrold:

  1. Als je scrollt terwijl de muisaanwijzer of het aanraakgebaar zich op de ::backdrop bevindt, scroll je de pagina eronder.
  2. Als je scrollt in de <dialog>, wordt de onderliggende pagina getoond zodra de scrollgrens van het dialoogvenster is bereikt of meteen als de content van het dialoogvenster niet overloopt.

Volgens de specificatie voor CSS-overscrollgedrag is overscroll-behavior van toepassing op alle scrollcontainer-elementen, waaronder niet-scrollbare scrollcontainers (elementen met overflow: hidden of overflow: auto waarvan de content op dit moment niet overloopt). Door overscroll-behavior: contain op de <dialog> te combineren met overflow: hidden en overscroll-behavior: contain op dialog::backdrop, kunt u voorkomen dat de onderliggende pagina scrollt met pure CSS.

Implementatie

1. Scroll chaining bevatten op de <dialog>

De user-agent-stylesheet stelt overflow: auto in op <dialog>, waardoor het standaard een scrollcontainer wordt. Pas overscroll-behavior: contain (of none) toe op dialog:modal (of dialog).

2. Maak van ::backdrop een scrollcontainer en beperk het scrollen

dialog::backdrop heeft standaard overflow: visible. Dit betekent dat het geen scrollcontainer is en overscroll-behavior negeert. Je moet overflow: hidden instellen op dialog::backdrop om er een niet-scrollbare scrollcontainer van te maken en deze koppelen aan overscroll-behavior: contain, zodat scrollgebaren die over de achtergrond worden uitgevoerd, worden vastgelegd en het onderliggende document niet bereiken.

Voorbeeldcode

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 practices en beperkingen

  • VERPLICHT: Stel overscroll-behavior: contain in voor het element <dialog> zelf (met de kiezer dialog:modal) en de dialog::backdrop. Zonder deze declaratie worden scrollgebaren over de achtergrond of in het dialoogvenster nog steeds gekoppeld aan de pagina.
  • VERPLICHT: Stel overflow: hidden (of overflow: auto) in op dialog::backdrop zodat het een scrollcontainer wordt. Zonder deze declaratie wordt ::backdrop standaard ingesteld op overflow: visible en heeft overscroll-behavior geen effect.
  • Gebruik overflow: clip of overflow: visible NIET op dialog::backdrop of dialog. Geen van beide waarden maakt een scrollcontainer, dus overscroll-behavior is niet van toepassing.
  • Pas overflow: hidden of position: fixed NIET toe op <html> of <body> om scrollen op de achtergrond te vergrendelen als een dialoogvenster wordt geopend. Als je de root-overflow muteert, wordt de schuifbalk van de pagina verwijderd (wat een horizontale verschuiving van de vormgeving veroorzaakt), kan de schuifpositie van de pagina worden gereset of verspringen en kunnen position: sticky-elementen op de onderliggende pagina worden verbroken.

Reservestrategieën

De CSS-property overscroll-behavior wordt ondersteund in alle grote browsers voor scrollcontainers met overvloeiende content, maar het respecteren van overscroll-behavior in niet-scrollbare scrollcontainers is een nieuwere specificatie die niet kan worden gedetecteerd.

Probeer NIET om ondersteuning voor niet-scrollbare containers te detecteren met @supports (overscroll-behavior: contain) of CSS.supports('overscroll-behavior', 'contain'). Alle moderne browsers ondersteunen de syntaxis van de property overscroll-behavior: contain en retourneren true, zelfs als ze deze alleen afdwingen als de content overloopt.

Behandel scroll-containment op niet-scrollbare scrollcontainers in plaats daarvan als een progressive enhancement:

  • In browsers die overscroll-behavior ondersteunen in niet-scrollbare scrollcontainers, wordt scrollen op de achtergrondpagina volledig voorkomen, zowel boven dialog::backdrop als in de <dialog> (of de content nu overloopt of niet).
  • In browsers die overscroll-behavior nog niet ondersteunen voor niet-scrollbare scrollcontainers, voorkomt overscroll-behavior: contain op dialog nog steeds scrollketens wanneer de eigen content van het dialoogvenster overloopt en scrollbaar is. Ondertussen houdt showModal() de toetsenbordfocus nog steeds vast en markeert het achtergronddocument inert.
  • We raden je aan progressive enhancement te gebruiken in plaats van verouderde tijdelijke oplossingen die overflow: hidden of position: fixed toepassen op <html> of <body>. Progressive enhancement verwijdert de hoofdscrollbar niet, veroorzaakt geen horizontale indelingsverschuivingen, springt niet naar de scrollpositie van de pagina en verstoort geen position: sticky-elementen op de onderliggende pagina.