שליטה בגלילה – התאמה אישית של אפקטים של 'משיכה לרענון' ו'אפשרויות נוספות'

אמ;לק

המאפיין overscroll-behavior ב-CSS מאפשר למפתחים לשנות את התנהגות ברירת המחדל של דפדפן בגלילה במקרה של עומס יתר כשמגיעים לחלק העליון או התחתון של התוכן. דוגמאות לתרחישים לדוגמה: השבתת התכונה 'משיכה לרענון' בנייד, הסרת האפקטים של התאורה והאלסטיות בזמן גלילה, מניעת גלילה של תוכן הדף כשהוא נמצא מתחת לחלון מודאלי או לשכבת-על.

רקע

גבולות גלילה ושרשור גלילה

שרשור גלילה ב-Chrome ל-Android.

גלילה היא אחת מהדרכים הבסיסיות ביותר ליצור אינטראקציה עם דף, אבל יכול להיות שיהיה קשה להתמודד עם דפוסי UX מסוימים בגלל התנהגויות ברירת המחדל המוזרות של הדפדפן. לדוגמה, תצוגת האפליקציות עם מספר רב של פריטים שהמשתמש עשוי לגלול ביניהם. כשהם מגיעים לתחתית, הגלילה בקונטיינר של עודף התוכן נעצרת כי אין יותר תוכן לצרוך. במילים אחרות, המשתמש מגיע ל'גבול גלילה'. אבל שימו לב למה שקורה אם המשתמש ממשיך לגלול. התוכן מאחורי המגירה מתחיל לגלול! הגלילה מועברת לקונטיינר ההורה, כלומר הדף הראשי עצמו בדוגמה.

מסתבר שההתנהגות הזו נקראת שרשור גלילה, והיא ברירת המחדל של הדפדפן כשגוללים בתוכן. לרוב ברירת המחדל טובה, אבל לפעמים היא לא רצויה או לא צפויה. יכול להיות שאפליקציות מסוימות ירצו לספק חוויית משתמש שונה כשהמשתמש מגיע לגבול גלילה.

האפקט של 'משיכה לרענון'

'משיכה לרענון' היא מחווה אינטואיטיבית שצוברת פופולריות באפליקציות לנייד כמו Facebook ו-Twitter. אם גוררים למטה את הפיד של הרשת החברתית ומשחררים, נוצר מקום חדש שבו נטענים פוסטים עדכניים יותר. למעשה, חוויית המשתמש הזו הפכה לפופולרית כל כך, שדפדפנים לנייד כמו Chrome ל-Android אימצו את אותו אפקט. החלקה למטה בחלק העליון של הדף מרעננת את הדף כולו:

האפשרות של Twitter לגרירה לרענון
כשמרעננים פיד ב-PWA.
פעולת 'משיכה לרענון' המובנית של Chrome ל-Android
מרעננת את הדף כולו.

במצבים כמו PWA של Twitter, מומלץ להשבית את הפעולה המקורית של משיכה לרענון. למה? באפליקציה הזו, סביר להניח שלא תרצו שהמשתמש יגרום לרענון הדף בטעות. יכול להיות שתראו גם אנימציה כפולה של רענון. לחלופין, יכול להיות שיהיה נחמד יותר להתאים אישית את הפעולה של הדפדפן, כך שתתאים יותר למיתוג של האתר. הבעיה היא שסוג ההתאמה האישית הזה היה קשה לביצוע. המפתחים נאלצו לכתוב קוד JavaScript מיותר, להוסיף חיישנים לא פסיביים למגע (שחוסמים את הגלילה) או להדביק את כל הדף ב-100vw/vh<div> (כדי למנוע מהדף לחרוג מעבר למסך). יש להן השפעות שליליות מוכרות על הביצועים של גלילה.

אנחנו יכולים לעשות טוב יותר!

חדש: overscroll-behavior

המאפיין overscroll-behavior הוא תכונה חדשה של CSS ששולטת בהתנהגות שמתרחשת כשגוללים מעבר לקו העליון של מאגר (כולל הדף עצמו). אפשר להשתמש בו כדי לבטל קישורי גלילה, להשבית או להתאים אישית את הפעולה של משיכה לרענון, להשבית את האפקטים של 'גמישות' ב-iOS (כש-Safari מטמיע את overscroll-behavior) ועוד. החלק הכי טוב הוא שהשימוש ב-overscroll-behavior לא משפיע לרעה על ביצועי הדף, בניגוד לפריצות שצוינו בפתיח.

למאפיין יש שלושה ערכים אפשריים:

  1. auto – ברירת המחדל. גלילות שמקורן ברכיב עשויות להופיע ברכיבי האב.
  2. contain – מונעת שרשור גלילה. גלילות לא מועברות לצאצאים, אבל השפעות מקומיות בתוך הצומת מוצגות. לדוגמה, אפקט ההילה של גלילה מעבר לקצה המסך ב-Android או אפקט הגומי ב-iOS, שמציג הודעה למשתמש כשהוא מגיע לקצה המסך. הערה: שימוש ב-overscroll-behavior: contain ברכיב html מונע פעולות ניווט של גלילה מעבר לקצה המסך.
  3. none – זהה ל-contain, אבל הוא גם מונע אפקטים של גלילה מעבר לקצה המסך בתוך הצומת עצמו (למשל, התאורה של גלילה מעבר לקצה המסך ב-Android או האלסטיות של גלילה ב-iOS).

נבחן כמה דוגמאות כדי להבין איך משתמשים ב-overscroll-behavior.

מניעת גלילה מחוץ לרכיב במיקום קבוע

התרחיש של תיבת הצ'אט

התוכן שמתחת לחלון הצ'אט גולל גם כן :(

כדאי להציב תיבת צ'אט במיקום קבוע בתחתית הדף. הכוונה היא שתיבת הצ'אט היא רכיב עצמאי, והיא גולשת בנפרד מהתוכן שמאחוריה. עם זאת, בגלל שרשור הגלילה, הגלילה במסמך תתחיל ברגע שהמשתמש ילחץ על ההודעה האחרונה בהיסטוריית הצ'אט.

באפליקציה הזו, עדיף שהגלילות שיוצאות מתיבת הצ'אט יישארו בתוך הצ'אט. כדי לעשות זאת, מוסיפים את הערך overscroll-behavior: contain לרכיב שמכיל את הודעות הצ'אט:

#chat .msgs {
  overflow: auto;
  overscroll-behavior: contain;
  height: 300px;
}

בעיקרון, אנחנו יוצרים הפרדה לוגית בין ההקשר של גלילה בתיבת הצ'אט לבין הדף הראשי. התוצאה הסופית היא שהדף הראשי נשאר במקום כשהמשתמש מגיע לחלק העליון או התחתון של היסטוריית הצ'אט. גלילות שמתחילות בתיבת הצ'אט לא מתפשטות.

התרחיש של שכבת-העל בדף

וריאנט נוסף של התרחיש 'גלילה מתחת למודעה' הוא מצב שבו התוכן גוללים מאחורי שכבת-על במיקום קבוע. הגיע הזמן למתנה מיוחדת overscroll-behavior. הדפדפן מנסה לעזור, אבל בסופו של דבר האתר נראה מלא באגים.

דוגמה – חלון דו-שיח עם overscroll-behavior: contain וללא overscroll-behavior: contain:

לפני: תוכן הדף גולל מתחת לשכבת-העל.
אחרי: תוכן הדף לא גוללים מתחת לשכבת-העל.

השבתת התכונה 'משיכה לרענון'

השבתה של הפעולה 'משיכה לרענון' היא שורה אחת של CSS. פשוט צריך למנוע שרשור גלילה בכל הרכיב שמגדיר את אזור התצוגה. ברוב המקרים, זהו הערך <html> או <body>:

body {
  /* Disables pull-to-refresh but allows overscroll glow effects. */
  overscroll-behavior-y: contain;
}

בעזרת התוספת הפשוטה הזו, אנחנו מתקנים את האנימציות הכפולות של משיכה לרענון בהדגמה של תיבת הצ'אט, ובמקום זאת יכולים להטמיע אפקט מותאם אישית שמשתמש באנימציית טעינה מסודרת יותר. גם תיבת הדואר הנכנס כולה מטושטשת בזמן הרענון:

לפני
אחרי

לפניכם קטע מתוך הקוד המלא:

<style>
  body.refreshing #inbox {
    filter: blur(1px);
    touch-action: none; /* prevent scrolling */
  }
  body.refreshing .refresher {
    transform: translate3d(0,150%,0) scale(1);
    z-index: 1;
  }
  .refresher {
    --refresh-width: 55px;
    pointer-events: none;
    width: var(--refresh-width);
    height: var(--refresh-width);
    border-radius: 50%;
    position: absolute;
    transition: all 300ms cubic-bezier(0,0,0.2,1);
    will-change: transform, opacity;
    ...
  }
</style>

<div class="refresher">
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
</div>

<section id="inbox"><!-- msgs --></section>

<script>
  let _startY;
  const inbox = document.querySelector('#inbox');

  inbox.addEventListener('touchstart', e => {
    _startY = e.touches[0].pageY;
  }, {passive: true});

  inbox.addEventListener('touchmove', e => {
    const y = e.touches[0].pageY;
    // Activate custom pull-to-refresh effects when at the top of the container
    // and user is scrolling up.
    if (document.scrollingElement.scrollTop === 0 && y > _startY &&
        !document.body.classList.contains('refreshing')) {
      // refresh inbox.
    }
  }, {passive: true});
</script>

השבתת האפקטים של זוהר בגלילה מעבר לקצה המסך ושל גמישויות

כדי להשבית את אפקט התנודות כשמגיעים לגבול הגלילה, משתמשים ב-overscroll-behavior-y: none:

body {
  /* Disables pull-to-refresh and overscroll glow effect.
     Still keeps swipe navigations. */
  overscroll-behavior-y: none;
}
לפני: כשמגיעים לקצה המסך מופיע זוהר.
אחרי: הארה מושבתת.

הדגמה מלאה

בסיכום, בהדמו המלא של תיבת הצ'אט נעשה שימוש ב-overscroll-behavior כדי ליצור אנימציה מותאמת אישית של 'משיכה לרענון' ולהשבית את האפשרות לגלול מחוץ לווידג'ט של תיבת הצ'אט. כך אפשר לספק חוויית משתמש אופטימלית, שיהיה קשה להשיג אותה בלי CSSoverscroll-behavior.

לצפייה בדמו | מקור