منع الصفحة الموجودة أسفل مربع حوار مشروط من التمرير

عند فتح عنصر <dialog> كنموذج باستخدام showModal()، يرقّيه المتصفّح إلى الطبقة العليا ويضع علامة على بقية المستند على أنّه غير نشط. وعلى الرغم من أنّ ذلك يحظر نقرات المؤشر وتركيز لوحة المفاتيح على الصفحة الأساسية، إلا أنّه لا يمنع الانتقال للأعلى أو للأسفل:

  1. يؤدي الانتقال للأعلى أو للأسفل أثناء وضع المؤشر أو إيماءة اللمس فوق ::backdrop إلى الانتقال في الصفحة أدناه.
  2. يؤدي الانتقال داخل <dialog> إلى الصفحة الأساسية بمجرد وصول مربّع الحوار إلى حدود الانتقال، أو على الفور إذا لم يتجاوز محتوى مربّع الحوار الحد الأقصى.

وفقًا لمواصفات سلوك تجاوز حد التمرير في CSS، تنطبق السمة overscroll-behavior على جميع عناصر حاويات التمرير، بما في ذلك حاويات التمرير غير القابلة للتمرير (العناصر التي تتضمّن overflow: hidden أو overflow: auto والتي لا يتجاوز محتواها الحدّ الأقصى حاليًا). من خلال دمج overscroll-behavior: contain في <dialog> مع overflow: hidden وoverscroll-behavior: contain في dialog::backdrop، يمكنك منع الانتقال إلى الصفحة الأساسية باستخدام CSS فقط.

التنفيذ

1. احتواء تسلسل الانتقال على <dialog>

تضبط ورقة أنماط وكيل المستخدم السمة overflow: auto على <dialog>، ما يجعلها حاوية قابلة للتمرير تلقائيًا. طبِّق overscroll-behavior: contain (أو none) على dialog:modal (أو dialog).

2. تحويل ::backdrop إلى حاوية قابلة للتمرير واحتواء التمرير فيها

بشكل تلقائي، يحتوي dialog::backdrop على overflow: visible، ما يعني أنّه ليس حاوية للتمرير ويتجاهل overscroll-behavior. يجب ضبط السمة overflow: hidden على dialog::backdrop لجعله حاوية تمرير غير قابلة للتمرير، وإقرانها بالسمة overscroll-behavior: contain بحيث يتم حظر إيماءات التمرير التي يتم تنفيذها فوق الخلفية ولا تصل إلى المستند الأساسي.

مثال على الرمز

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

أفضل الممارسات والقيود

  • إلزامي: اضبط السمة overscroll-behavior: contain على عنصر <dialog> نفسه (باستخدام أداة الاختيار dialog:modal) وdialog::backdrop. بدون هذا التعريف، ستظل إيماءات الانتقال فوق الخلفية أو داخل مربّع الحوار مرتبطة بالصفحة.
  • إلزامي: اضبط السمة overflow: hidden (أو overflow: auto) على dialog::backdrop ليصبح حاوية قابلة للتمرير. بدون هذا البيان، يتم ضبط السمة ::backdrop تلقائيًا على overflow: visible ولن يكون للسمة overscroll-behavior أي تأثير.
  • لا تستخدم overflow: clip أو overflow: visible على dialog::backdrop أو dialog. لا تنشئ أي من القيمتَين حاوية قابلة للتمرير، لذا لن يتم تطبيق السمة overscroll-behavior.
  • لا تطبّق overflow: hidden أو position: fixed على <html> أو <body> لقفل الانتقال في الخلفية عند فتح مربّع حوار. يؤدي تغيير تجاوز الجذر إلى إزالة شريط التمرير في الصفحة (ما يتسبب في تغيير التنسيق الأفقي)، ويمكن أن يؤدي إلى إعادة ضبط موضع تمرير الصفحة أو الانتقال إليه، ويمكن أن يؤدي إلى تعطُّل عناصر position: sticky في الصفحة الأساسية.

الاستراتيجيات الاحتياطية

على الرغم من أنّ السمة overscroll-behavior في CSS متوافقة مع جميع المتصفّحات الرئيسية لحاويات الانتقال التي تتضمّن محتوى فائضًا، فإنّ الالتزام بالسمة overscroll-behavior في حاويات الانتقال غير القابلة للانتقال هو مواصفات أحدث لا يمكن رصدها.

لا تحاول رصد ميزة دعم الحاويات غير القابلة للتمرير باستخدام @supports (overscroll-behavior: contain) أو CSS.supports('overscroll-behavior', 'contain'). تتوافق جميع المتصفّحات الحديثة مع بنية السمة overscroll-behavior: contain وتعرض القيمة true، حتى إذا كانت تفرضها فقط عندما يتجاوز المحتوى الحدّ المسموح به.

بدلاً من ذلك، يمكنك التعامل مع احتواء التمرير في حاويات التمرير غير القابلة للتمرير على أنّه تحسين تدريجي:

  • في المتصفّحات التي تتيح استخدام overscroll-behavior في حاويات الانتقال غير القابلة للتمرير، يتم منع الانتقال في الصفحة في الخلفية تمامًا على كل من dialog::backdrop وداخل <dialog> (سواء كان محتواها يتجاوز الحدّ المسموح به أم لا).
  • في المتصفّحات التي لا تتيح بعد استخدام السمة overscroll-behavior في حاويات التمرير غير القابلة للتمرير، تمنع السمة overscroll-behavior: contain في dialog تسلسل التمرير عندما يتجاوز محتوى مربّع الحوار الحدّ الأقصى ويكون قابلاً للتمرير. في الوقت نفسه، لا يزال showModal() يحبس تركيز لوحة المفاتيح ويضع علامة على مستند الخلفية inert.
  • ننصح بالاعتماد على التحسين التدريجي بدلاً من الحلول البديلة القديمة التي تطبّق overflow: hidden أو position: fixed على <html> أو <body>، لأنّها لا تزيل شريط التمرير الجذر أو تتسبّب في تغييرات في التصميم الأفقي أو تغيّر موضع الانتقال في الصفحة أو تؤدي إلى تعطُّل عناصر position: sticky في الصفحة الأساسية.