אפשר ליצור חוויות גלילה מבוקרות היטב על ידי הצהרה על מיקומי גלילה עם נקודות עצירה (scroll snapping).
התכונה CSS Scroll Snap מאפשרת למפתחי אתרים ליצור חוויות גלילה מבוקרות היטב על ידי הצהרה על מיקומי גלילה עם נקודות עצירה. מאמרים עם דפים וקרוסלות של תמונות הם שתי דוגמאות נפוצות לכך. CSS Scroll Snap מספק API עקבי וקל לשימוש ליצירת דפוסי חוויית המשתמש הפופולריים האלה.
רקע
למה כדאי להשתמש בגלילה עם נקודות עצירה (scroll snapping)
גלילה היא דרך פופולרית וטבעית לבצע פעולות בתוכן באינטרנט. זו הדרך המקורית של הפלטפורמה לספק גישה למידע נוסף מעבר למה שמוצג במסך בבת אחת, והיא חיונית במיוחד בפלטפורמות לנייד עם שטח מסך מוגבל. לכן, לא מפתיע שיוצרי תוכן באינטרנט מעדיפים יותר ויותר לארגן את התוכן ברשימות שטוחות שאפשר לגלול בהן, ולא בהיררכיות עמוקות.
החיסרון העיקרי של הגלילה הוא חוסר הדיוק שלה. לעיתים רחוקות הגלילה מסתיימת כשהיא מיושרת לפסקה או למשפט. ההשפעה הזו בולטת עוד יותר בתוכן שמחולק לדפים או לפריטים עם גבולות משמעותיים, כשהגלילה מסתיימת באמצע הדף או התמונה, ומשאירה אותם גלויים באופן חלקי. בתרחישים לדוגמה האלה, חוויית גלילה מבוקרת היטב היא יתרון.
מפתחי אתרים מסתמכים כבר זמן רב על פתרונות מבוססי-JavaScript כדי לשלוט בגלילה ולעזור לטפל בחיסרון הזה. עם זאת, פתרונות שמבוססים על JavaScript לא מספקים פתרון נאמן למקור בגלל חוסר בפרימיטיבים להתאמה אישית של הגלילה או בגישה לגלילה משולבת. התכונה "גלילה עם נקודות עצירה (scroll snapping) ב-CSS" מבטיחה פתרון מהיר, מדויק וקל לשימוש שפועל באופן עקבי בכל הדפדפנים.
גלילה עם נקודות עצירה (scroll snapping) ב-CSS מאפשרת ליוצרי אתרים לסמן כל מאגר גלילה בגבולות לפעולות גלילה שבהן צריך לסיים. לאחר מכן, הדפדפנים בוחרים את מיקום הסיום המתאים ביותר בהתאם לפרטים של פעולת הגלילה, הפריסה והניראות של מאגר הגלילה והפרטים של מיקומי ההצמדה, ואז מפעילים אנימציה חלקה אליו. נחזור לדוגמה הקודמת: כשהמשתמש מסיים לגלול את הקרוסלה, התמונה שמוצגת נצמדת למקום. אין צורך בשינויים בגלילה באמצעות JavaScript.
גלילה עם נקודות עצירה (scroll snapping) ב-CSS
גלילה עם נקודות עצירה (scroll snapping) היא פעולה שבה מתאימים את היסט הגלילה של מאגר גלילה כך שיהיה במיקום העצירה המועדף בסיום פעולת הגלילה.
כדי להפעיל גלילה עם נקודות עצירה בקונטיינר גלילה, משתמשים במאפיין scroll-snap-type. המאפיין הזה מציין לדפדפן שהוא צריך לשקול להצמיד את מאגר הגלילה הזה למיקומי ההצמדה שנוצרו על ידי הצאצאים שלו. scroll-snap-type
קובע את הציר שבו מתרחשת הגלילה: x, y או both, ואת
רמת ההצמדה: mandatory, proximity. בהמשך נרחיב על הנושאים האלה.
כדי ליצור מיקום הצמדה, צריך להגדיר את היישור הרצוי של רכיב.
המיקום הזה הוא היסט הגלילה שבו המאגר הקרוב ביותר של רכיבי הגלילה והרכיב מיושרים לפי הציר הנתון. אפשר ליישר את הרכיבים בכל ציר בדרכים הבאות: start, end, center.
יישור start פירושו שקצה ההתחלה של אזור ההצמדה של מאגר הגלילה צריך להיות מיושר עם קצה ההתחלה של אזור ההצמדה של הרכיב. באופן דומה, היישורים end ו-center מציינים שהקצה או המרכז של נקודת ההצמדה של מאגר הגלילה צריכים להיות מיושרים עם הקצה או המרכז של אזור ההצמדה של הרכיב.
הדוגמאות הבאות ממחישות איך להשתמש במושגים האלה.
דוגמה: גלריה אופקית
תרחיש נפוץ לשימוש בגלילה עם נקודות עצירה הוא קרוסלת תמונות. לדוגמה, כדי ליצור קרוסלת תמונות אופקית שמתמקדת בכל תמונה כשגוללים, אפשר להגדיר שמאפיין הגלילה של הקונטיינר יכלול את הערך scroll-snap-type בציר האופקי.
מגדירים לכל תמונה את הערך scroll-snap-align: center כדי לוודא שההתמקדות תמרכז את התמונה בתוך הקרוסלה.
#gallery {
scroll-snap-type: x mandatory;
overflow-x: scroll;
display: flex;
}
#gallery img {
scroll-snap-align: center;
}
<div id="gallery">
<img src="cat.jpg">
<img src="dog.jpg">
<img src="another_cute_animal.jpg">
</div>
מכיוון שמיקומי ההצמדה משויכים לרכיב, אלגוריתם ההצמדה יכול להיות חכם לגבי מתי ואיך הוא מצמיד בהתאם לרכיב ולגודל של מאגר הגלילה. לדוגמה, נניח שיש תמונה אחת שגדולה יותר מהקרוסלה. אלגוריתם הצמדה פשוט עלול למנוע מהמשתמש להזיז את התמונה כדי לראות אותה במלואה. אבל המפרט דורש מההטמעות לזהות את המקרה הזה ולאפשר למשתמש לגלול בחופשיות בתוך התמונה, כך שההצמדה תתבצע רק בקצוות שלה.
דוגמה: דף מוצר עם מסלול המרה
מקרה נפוץ נוסף שבו כדאי להשתמש בגלילה עם נקודות עצירה הוא דפים עם כמה קטעים לוגיים שצריך לגלול בהם אנכית, למשל דף מוצר טיפוסי. scroll-snap-type: y proximity; מתאים יותר למקרים כאלה. הוא לא מפריע כשמשתמשים גוללים לאמצע של קטע מסוים, אבל הוא גם נצמד לקטע חדש ומפנה אליו את תשומת הלב כשהם גוללים קרוב מספיק.
כך אפשר לעשות את זה:
article {
scroll-snap-type: y proximity;
/* Reserve space for header plus some extra space for sneak peeking. */
scroll-padding-top: 15vh;
overflow-y: scroll;
}
section {
/* Snap align start. */
scroll-snap-align: start;
}
header {
position: fixed;
height: 10vh;
}
<article>
<header> Header </header>
<section> Section One </section>
<section> Section Two </section>
<section> Section Three </section>
</article>
מרווח פנימי ושוליים של גלילה
בדף המוצר יש כותרת עליונה במיקום קבוע. בנוסף, העיצוב דרש שחלק מהקטע העליון יישאר גלוי כשמכל הגלילה נצמד, כדי לספק למשתמשים רמז עיצובי לגבי התוכן שמעל.
המאפיין scroll-padding הוא מאפיין CSS חדש שמאפשר לשנות את האזור האפקטיבי שניתן לצפייה של מאגר הגלילה, או snapport, שמשמש לחישוב היישורים של גלילה עם נקודות עצירה (scroll snapping). המאפיין מגדיר הסטה (inset) ביחס לתיבת המרווח הפנימי של מאגר הגלילה. בדוגמה שלנו, הוספנו עוד 15vh לחלק העליון, מה שמורה לדפדפן להתייחס למיקום נמוך יותר, 15vh מתחת לקצה העליון של מאגר הגלילה, כקצה ההתחלה האנכי שלו לגלילה עם נקודות עצירה. בזמן ההצמדה, הקצה העליון של רכיב היעד להצמדה יתיישר עם המיקום החדש הזה, וכך יישאר רווח מעליו.
המאפיין scroll-margin מגדיר את ערך ה-outset שמשמש להתאמת התיבה האפקטיבית של יעד ההצמדה, בדומה לאופן שבו scroll-padding פועל במאגר הגלילה עם ההצמדה.
אולי שמתם לב שהמילה "snap" לא מופיעה בשני המאפיינים האלה. זה מכוון, כי הם משנים בפועל את התיבה לכל פעולות הגלילה הרלוונטיות, ולא רק את הגלילה עם נקודות העצירה. לדוגמה, Chrome מביא אותם בחשבון כשהוא מחשב את גודל הדף לפעולות גלילה בדפים כמו PageDown ו-PageUp, וגם כשהוא מחשב את כמות הגלילה לפעולה Element.scrollIntoView().
אינטראקציה עם ממשקי API אחרים של גלילה
DOM Scrolling API
גלילה עם נקודות עצירה מתרחשת אחרי כל פעולות הגלילה, כולל אלה שמופעלות על ידי סקריפט. כשמשתמשים בממשקי API כמו Element.scrollTo, הדפדפן מחשב את מיקום הגלילה הרצוי של הפעולה, ואז מחיל את הלוגיקה המתאימה של ההצמדה כדי למצוא את המיקום הסופי של ההצמדה. לכן, אין צורך בסקריפט משתמש כדי לבצע חישובים ידניים להצמדה.
גלילה חלקה
גלילה חלקה שולטת בהתנהגות של פעולת גלילה פרוגרמטית, וגלילה עם נקודות עצירה קובעת את היעד שלה. מכיוון שהם שולטים בהיבטים אורתוגונליים של הגלילה, אפשר להשתמש בהם ביחד והם משלימים זה את זה.
התנהגות של גלילה מעבר לקצה
ה-API של התנהגות גלילת-יתר קובע איך הגלילה משורשרת בין כמה רכיבים, והוא לא מושפע מגלילה עם נקודות עצירה.
אזהרות ושיטות מומלצות
הימנעו משימוש בהצמדה חובה כשיש רווחים גדולים בין רכיבי היעד. זה יכול לגרום לכך שלא תהיה גישה לתוכן שנמצא בין מיקומי ההצמדה.
בהרבה מקרים אפשר להוסיף גלילה עם נקודות עצירה כשיפור בלי צורך בזיהוי תכונות.
אם צריך, אפשר להשתמש ב-@supports או ב-CSS.supports כדי לזהות תמיכה ב-CSS Scroll Snap.
אל תשתמשו ב-scroll-snap-type, שמופיע גם במפרט שהוצא משימוש.
זיהוי תכונות ב-CSS
@supports (scroll-snap-align: start) {
article {
scroll-snap-type: y proximity;
scroll-padding-top: 15vh;
overflow-y: scroll;
}
}
זיהוי תכונות ב-JavaScript
if (CSS.supports('scroll-snap-align: start')) {
// use css scroll snap
} else {
// use fallback
}
אל תניחו שממשקי API לגלילה פרוגרמטית כמו Element.scrollTo תמיד מסתיימים בהיסט הגלילה המבוקש. גלילה עם נקודות עצירה (scroll snapping) עשויה לשנות את היסט הגלילה אחרי שהגלילה הפרוגרמטית מסתיימת. חשוב לציין שזו לא הייתה הנחה נכונה גם לפני הגלילה עם נקודות העצירה, כי יכול להיות שהגלילה הופסקה מסיבות אחרות, אבל זה נכון במיוחד לגבי גלילה עם נקודות עצירה.
עבודה עתידית
חוויית הגלילה הייתה המוקד של סקר שנערך לאחרונה על ידי צוות Chrome.
תוצאות הסקר זיהו כמה תחומים שצריך לעבוד עליהם כדי לצמצם את הפער בין ספריות הפלאגינים לבין CSS.
העבודה הקרובה תתמקד בscroll-snap, כולל:
- זמינות ותאימות של ממשקי API בדפדפנים שונים.
- עבודה על ממשקי CSS API חדשים כמו
scroll-start. - עובדים על אירועי JS חדשים כמו
snapChanged().