التمرير كذاب على مواقع الويب الخاصة بك
نشرت: 2022-03-10overscroll-behavior
، الذي تم تنفيذه في Chrome في ديسمبر 2017 وفي Firefox في مارس 2018 ، في هذه المقالة. إن الفهم الجيد لهذا التأثير مفيد جدًا لبناء أو تصميم أي موقع ويب يحتوي على عناصر ثابتة.غالبًا ما يتم استخدام ارتداد التمرير (يشار إليه أحيانًا باسم التمرير "الشريط المطاطي" أو "التمرير المرن") للإشارة إلى التأثير الذي تراه عند التمرير إلى أعلى الصفحة أو عنصر HTML ، أو إلى أسفل صفحة أو عنصر ، على جهاز يستخدم شاشة تعمل باللمس أو لوحة تعقب ، ويمكن رؤية مساحة فارغة للحظة قبل أن يعود العنصر أو الصفحة للخلف ويصطف مرة أخرى إلى أعلى / أسفل (عند تحرير اللمس / أصابعك). يمكنك أن ترى تأثيرًا مشابهًا يحدث في محاذاة التمرير بين العناصر في CSS.
ومع ذلك ، تركز هذه المقالة على التمرير المرتد عند التمرير إلى أعلى أو أسفل صفحة الويب. بمعنى آخر ، عندما يصل منفذ التمرير إلى حدود التمرير الخاصة به.
جمع البيانات ، الطريقة القوية
هل تعلم أنه يمكن استخدام CSS لجمع الإحصائيات؟ في الواقع ، هناك أيضًا نهج CSS فقط لتتبع تفاعلات واجهة المستخدم باستخدام Google Analytics. اقرأ مقالًا ذا صلة ←
يعد الفهم الجيد لارتداد التمرير مفيدًا جدًا لأنه سيساعدك على تحديد كيفية إنشاء مواقع الويب الخاصة بك وكيف تريد تمرير الصفحة.
ارتداد التمرير غير مرغوب فيه إذا كنت لا تريد رؤية العناصر fixed
أثناء نقل الصفحة. تتضمن بعض الأمثلة: عندما تريد تثبيت رأس أو تذييل في موضع معين ، أو إذا كنت تريد تثبيت أي عنصر آخر مثل القائمة ، أو إذا كنت تريد أن يتم تمرير الصفحة بسرعة في مواضع معينة في التمرير و لا تريد أن يحدث أي تمرير إضافي في الجزء العلوي أو السفلي من الصفحة مما يؤدي إلى إرباك زوار موقع الويب الخاص بك. ستقترح هذه المقالة بعض الحلول للمشكلات التي تواجه عند التعامل مع ارتداد التمرير في أعلى أو أسفل صفحة الويب.
أول لقاء لي مع التأثير
لاحظت هذا التأثير لأول مرة عندما كنت أقوم بتحديث موقع ويب أنشأته منذ وقت طويل. يمكنك عرض الموقع هنا. كان من المفترض أن يكون التذييل الموجود أسفل الصفحة ثابتًا في موضعه أسفل الصفحة ولا يتحرك على الإطلاق. في الوقت نفسه ، كان من المفترض أن تكون قادرًا على التمرير لأعلى ولأسفل خلال المحتويات الرئيسية للصفحة. من الناحية المثالية ، ستعمل على النحو التالي:

يعمل حاليًا بهذه الطريقة في Firefox أو على أي متصفح على جهاز بدون شاشة تعمل باللمس أو لوحة تتبع. ومع ذلك ، في ذلك الوقت ، كنت أستخدم Chrome على جهاز MacBook. كنت أقوم بالتمرير إلى أسفل الصفحة باستخدام لوحة التتبع عندما اكتشفت أن موقع الويب الخاص بي لا يعمل بشكل صحيح. يمكنك أن ترى ما حدث هنا:

أوه لا! لم يكن هذا ما كان من المفترض أن يحدث! لقد قمت بتعيين موضع التذييل ليكون في أسفل الصفحة عن طريق تعيين خاصية position
CSS الخاصة به إلى قيمة fixed
. وهذا هو الوقت المناسب أيضًا لإعادة النظر في position: fixed;
يكون. وفقًا لمواصفات CSS 2.1 ، عند إصلاح "مربع" (في هذه الحالة ، التذييل الأزرق الداكن) ، يكون "ثابتًا فيما يتعلق بإطار العرض ولا يتحرك عند التمرير". ما يعنيه هذا هو أنه لم يكن من المفترض أن يتحرك التذييل عند التمرير لأعلى ولأسفل الصفحة. كان هذا ما يقلقني عندما رأيت ما كان يحدث على Chrome.
لجعل هذه المقالة أكثر اكتمالًا ، سأوضح لك كيف يتم تمرير الصفحة على كل من Mobile Edge و Mobile Safari و Desktop Safari أدناه. هذا يختلف عما يحدث عند التمرير على Firefox و Chrome. آمل أن يمنحك هذا فهمًا أفضل لكيفية عمل نفس الرمز بالضبط حاليًا بطرق مختلفة. يعد تطوير التمرير الذي يعمل بنفس الطريقة عبر متصفحات الويب المختلفة تحديًا حاليًا.

البحث عن حل
كانت إحدى أفكاري الأولى أنه ستكون هناك طريقة سهلة وسريعة لإصلاح هذه المشكلة على جميع المتصفحات. ما يعنيه هذا هو أنني اعتقدت أنه يمكنني إيجاد حل يستغرق بضعة أسطر من كود CSS وأنه لن يتم تضمين JavaScript. لذلك ، كان من أول الأشياء التي قمت بها هو محاولة تحقيق ذلك. تضمنت المتصفحات التي استخدمتها للاختبار Chrome و Firefox و Safari على macOS و Windows 10 و Edge و Safari على iOS. كانت إصدارات هذه المتصفحات هي الأحدث وقت كتابة هذا المقال (2018).
حلول HTML و CSS فقط
تحديد المواقع المطلقة والنسبية
من أول الأشياء التي جربتها ، استخدام الموضع المطلق والنسبي لوضع التذييل لأنني كنت معتادًا على بناء تذييلات مثل هذا. تتمثل الفكرة في ضبط صفحة الويب الخاصة بي على ارتفاع 100٪ بحيث يكون التذييل دائمًا في أسفل الصفحة بارتفاع ثابت ، بينما يشغل المحتوى 100٪ مطروحًا منه ارتفاع التذييل ويمكنك التمرير عبر ذلك. بدلاً من ذلك ، يمكنك تعيين padding-bottom
بدلاً من استخدام calc
وتعيين ارتفاع body-container
إلى 100٪ بحيث لا تتداخل محتويات التطبيق مع التذييل. بدا رمز CSS كما يلي:
html { width: 100%; height: 100%; overflow: hidden; position: relative; } body { width: 100%; margin: 0; font-family: sans-serif; height: 100%; overflow: hidden; } .body-container { height: calc(100% - 100px); overflow: auto; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: absolute; bottom: 0; height: 100px; width: 100%; }
يعمل هذا الحل تقريبًا بنفس طريقة الحل الأصلي (الذي كان مجرد position: fixed;
). تتمثل إحدى مزايا هذا الحل مقارنةً بذلك في أن التمرير ليس للصفحة بأكملها ، ولكن لمحتويات الصفحة فقط بدون تذييل الصفحة. أكبر مشكلة في هذه الطريقة هي أنه في Mobile Safari ، يتحرك كل من التذييل ومحتويات التطبيق في نفس الوقت. هذا يجعل هذا النهج إشكاليًا للغاية عند التمرير بسرعة:

كان من الصعب ملاحظة تأثير آخر لم أكن أريده في البداية ، وأدركت أنه كان يحدث فقط بعد تجربة المزيد من الحلول. كان هذا هو أنه كان التمرير خلال محتويات طلبي أبطأ قليلاً. نظرًا لأننا نضبط ارتفاع حاوية التمرير الخاصة بنا على 100٪ من نفسها ، فإن هذا يعيق التمرير المستند إلى النقر / الزخم على نظام التشغيل iOS. إذا كان هذا الارتفاع بنسبة 100٪ أقصر (على سبيل المثال ، عندما يصبح ارتفاع 100٪ بمقدار 2000 بكسل ارتفاعًا بنسبة 100٪ بمقدار 900 بكسل) ، فإن التمرير المستند إلى الزخم يصبح أسوأ. يحدث التمرير المستند إلى الزخم / النقر عند النقر فوق سطح شاشة تعمل باللمس بأصابعك ويتم تمرير الصفحة من تلقاء نفسها. في حالتي ، أردت أن يحدث التمرير المستند إلى الزخم بحيث يمكن للمستخدمين التمرير بسرعة ، لذلك بقيت بعيدًا عن الحلول التي تحدد ارتفاعًا بنسبة 100٪.

محاولات أخرى
أحد الحلول المقترحة على الويب ، والذي حاولت استخدامه في الكود الخاص بي ، موضح أدناه كمثال.
html { width: 100%; position: fixed; overflow: hidden; } body { width: 100%; margin: 0; font-family: sans-serif; position: fixed; overflow: hidden; } .body-container { width: 100vw; height: calc(100vh - 100px); overflow-y: auto; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: fixed; bottom: 0; height: 100px; width: 100%; }
يعمل هذا الرمز على Chrome و Firefox على macOS بنفس طريقة الحل السابق. ميزة هذه الطريقة هي أن التمرير لا يقتصر على ارتفاع 100٪ ، لذا فإن التمرير المستند إلى الزخم يعمل بشكل صحيح. ومع ذلك ، يختفي التذييل في Safari:

في iOS Safari ، يصبح التذييل أقصر ، وهناك فجوة إضافية شفافة (أو بيضاء) في الأسفل. أيضًا ، تُفقد القدرة على التمرير عبر الصفحة بعد التمرير إلى أسفل الصفحة. يمكنك رؤية الفجوة البيضاء أسفل التذييل هنا:

أحد السطور المثيرة للاهتمام من التعليمات البرمجية التي قد تراها كثيرًا هو: -webkit-overflow-scrolling: touch;
. الفكرة وراء ذلك هي أنه يسمح بالتمرير المستند إلى الزخم لعنصر معين. توصف هذه الخاصية بأنها "غير قياسية" و "ليست على المسار القياسي" في وثائق MDN. تظهر كـ "قيمة خاصية غير صالحة" قيد الفحص في Firefox و Chrome ، ولا تظهر كملكية على Desktop Safari. لم أستخدم خاصية CSS هذه في النهاية.
لإظهار مثال آخر لحل قد تواجهه ونتيجة مختلفة وجدتها ، جربت أيضًا الكود أدناه:
html { position: fixed; height: 100%; overflow: hidden; } body { font-family: sans-serif; margin: 0; width: 100vw; height: 100vh; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 110px; } footer { position: fixed; }
يعمل هذا في الواقع بشكل جيد عبر متصفحات سطح المكتب المختلفة ، ولا يزال التمرير المستند إلى الزخم يعمل ، ويتم إصلاح التذييل في الجزء السفلي ولا يتحرك على متصفحات الويب لسطح المكتب. ربما يكون الجزء الأكثر إشكالية في هذا الحل (وما يجعله فريدًا) هو أنه في iOS Safari ، يهتز التذييل دائمًا ويشوه قليلاً جدًا ويمكنك رؤية المحتوى الموجود أسفله كلما قمت بالتمرير.
حلول مع JavaScript
بعد تجربة بعض الحلول الأولية باستخدام HTML و CSS فقط ، قمت بتجربة بعض حلول JavaScript. أود أن أضيف أن هذا شيء لا أنصحك به وسيكون من الأفضل تجنبه. من واقع خبرتي ، عادة ما تكون هناك حلول أكثر أناقة وإيجازًا باستخدام HTML و CSS فقط. ومع ذلك ، فقد قضيت بالفعل الكثير من الوقت في تجربة الحلول الأخرى ، واعتقدت أنه لن يضر بسرعة معرفة ما إذا كانت هناك بعض الحلول البديلة التي تستخدم JavaScript.
المس الأحداث
تتمثل إحدى طرق حل مشكلة ارتداد التمرير في منع أحداث touchmove
أو touchstart
على window
أو document
. تكمن الفكرة وراء ذلك في منع أحداث اللمس على النافذة الكلية ، بينما يُسمح بأحداث اللمس على المحتوى الذي تريد التمرير خلاله. يظهر مثال على رمز مثل هذا أدناه:
// Prevents window from moving on touch on older browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, false) // Allows content to move on touch. document.querySelector('.body-container').addEventListener('touchmove', function (event) { event.stopPropagation() }, false)
لقد جربت العديد من أشكال هذا الرمز لمحاولة جعل التمرير يعمل بشكل صحيح. منع touchmove
على window
لم يحدث فرقًا. استخدام document
لم يحدث فرقا. حاولت أيضًا استخدام كل من touchstart
و touchmove
للتحكم في التمرير ، لكن هاتين الطريقتين أيضًا لم تحدثا أي فرق. تعلمت أنه لم يعد بإمكانك استدعاء event.preventDefault()
بهذه الطريقة لأسباب تتعلق بالأداء. عليك ضبط الخيار passive
على false
في مستمع الحدث:
// Prevents window from moving on touch on newer browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, {passive: false})
مكتبات
قد تصادف مكتبة تسمى "iNoBounce" والتي تم تصميمها "لإيقاف تطبيق iOS webapp الخاص بك من الارتداد عند التمرير". شيء واحد يجب ملاحظته عند استخدام هذه المكتبة في الوقت الحالي لحل المشكلة التي وصفتها في هذه المقالة هو أنها تحتاج إلى استخدام -webkit-overflow-scrolling
. شيء آخر يجب ملاحظته هو أن الحل الأكثر إيجازًا الذي انتهيت إليه (والذي تم وصفه لاحقًا) يفعل شيئًا مشابهًا كما هو الحال في نظام التشغيل iOS. يمكنك اختبار ذلك بنفسك من خلال النظر إلى الأمثلة الموجودة في مستودع GitHub ومقارنتها بالحل الذي انتهيت إليه.
سلوك التمرير الزائد
بعد تجربة كل هذه الحلول ، اكتشفت overscroll-behavior
لخاصية CSS. تم تنفيذ خاصية CSS overscroll-behavior
في Chrome 63 في ديسمبر 2017 ، وفي Firefox 59 في مارس 2018. هذه الخاصية ، كما هو موضح في وثائق MDN ، "تتيح لك التحكم في سلوك تجاوز التمرير بالمتصفح - ما يحدث عندما تكون حدود تم الوصول إلى منطقة التمرير ". كان هذا هو الحل الذي انتهيت من استخدامه.
كل ما كان علي فعله هو ضبط overscroll-behavior
على none
في body
موقع الويب الخاص بي ويمكنني ترك position
fixed
كما هو. على الرغم من تطبيق التمرير المستند إلى الزخم على الصفحة بأكملها ، بدلاً من المحتويات بدون تذييل الصفحة ، إلا أن هذا الحل كان جيدًا بما يكفي بالنسبة لي ويلبي جميع متطلباتي في ذلك الوقت ، ولم يعد تذييل يرتد بشكل غير متوقع على Chrome. ربما يكون من المفيد ملاحظة أن Edge قد تم وضع علامة على هذه الخاصية على أنها قيد التطوير الآن. يمكن اعتبار overscroll-behavior
بمثابة تحسين إذا لم تدعمه المتصفحات بعد.
خاتمة
إذا كنت لا تريد أن ترتد الرؤوس أو التذييلات الثابتة على صفحات الويب الخاصة بك ، فيمكنك الآن استخدام خاصية CSS الخاصة overscroll-behavior
.
على الرغم من حقيقة أن هذا الحل يعمل بشكل مختلف في المتصفحات المختلفة (لا يزال ارتداد محتوى الصفحة يحدث على Safari و Edge ، بينما لا يحدث ذلك في Firefox و Chrome) ، فإنه سيبقي الرأس أو التذييل ثابتًا عند التمرير إلى الأعلى. أو أسفل موقع الويب. إنه حل موجز وفي جميع المتصفحات التي تم اختبارها ، لا يزال التمرير المستند إلى الزخم يعمل ، بحيث يمكنك التمرير عبر الكثير من محتوى الصفحة بسرعة كبيرة. إذا كنت تقوم بإنشاء رأس أو تذييل ثابت على صفحة الويب الخاصة بك ، فيمكنك البدء في استخدام هذا الحل.