جلوگیری از پیمایش صفحه زیر کادر گفتگوی مدال

ویژگی‌های وب: overscroll-behavior <dialog> ::backdrop :modal

وقتی عنصر <dialog> به‌عنوان مدال بااستفاده از showModal() باز می‌شود، مرورگر آن را به لایه بالایی ارتقا می‌دهد و بقیه سند را به‌عنوان بی‌اثر علامت‌گذاری می‌کند. درحالی‌که این کار کلیک‌های اشاره‌گر و تمرکز صفحه‌کلید را در صفحه زیرین مسدود می‌کند، از پیمایش جلوگیری نمی‌کند:

  1. پیمایش کردن وقتی اشاره‌گر یا اشاره لمسی روی ::backdrop است، صفحه زیرین را پیمایش می‌کند.
  2. پیمایش درون <dialog> به صفحه زیرین زنجیر می‌شود، وقتی کادر گفتگو به مرز پیمایش خود می‌رسد—یا بلافاصله اگر محتوای کادر گفتگو سرریز نشود.

طبق مشخصات CSS Overscroll Behavior،‏ overscroll-behavior برای همه عناصر محفظه پیمایش اعمال می‌شود، ازجمله محفظه‌های پیمایش غیرقابل‌پیمایش (عناصر با overflow: hidden، یا overflow: auto که محتوای آن‌ها درحال‌حاضر سرریز نمی‌شود). با ترکیب کردن overscroll-behavior: contain در <dialog> با overflow: hidden و overscroll-behavior: contain در dialog::backdrop، می‌توانید بااستفاده از CSS خالص از پیمایش صفحه زیرین جلوگیری کنید.

پیاده‌سازی

۱. Contain scroll chaining on the <dialog>

شیوه‌نامه نماینده کاربر overflow: auto را روی <dialog> تنظیم می‌کند و آن را به‌طور پیش‌فرض به محفظه پیمایش تبدیل می‌کند. ‫overscroll-behavior: contain (یا none) را به dialog:modal (یا dialog) اعمال کنید.

۲. ‫::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 را در صفحه زیرین خراب کند.

راهبردهای جایگزین

درحالی‌که ویژگی CSS overscroll-behavior در همه مرورگرهای اصلی برای محفظه‌های پیمایش که محتوای سرریز دارند پشتیبانی می‌شود، رعایت 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 را در صفحه زیرین خراب نمی‌کند.