כדי ליצור חוויות גלילה מבוקרות, אפשר להצהיר על מיקומי הצמדה בגלילה.
התכונה CSS Scroll Snap מאפשרת למפתחי אינטרנט ליצור חוויות גלילה מבוקרות היטב על ידי הצהרה על מיקומי נעילה של גלילה. מאמרים שמחולקים לדפים וקרוסלות של תמונות הם שתי דוגמאות נפוצות לכך. CSS Scroll Snap מספק ממשק API עקבי וקל לשימוש ליצירת דפוסי חוויית המשתמש הפופולריים האלה.
רקע
למה כדאי להשתמש ב'הצמדה לגלילה'
גלילה היא דרך פופולרית וטבעית ליצור אינטראקציה עם תוכן באינטרנט. זהו אמצעי מקורי של הפלטפורמה לספק גישה למידע רב יותר ממה שגלוי במסך בבת אחת, והוא הופך להיות חיוני במיוחד בפלטפורמות לנייד עם שטח מסך מוגבל. לכן, לא מפתיע שכותבי אתרים מעדיפים יותר ויותר לארגן את התוכן ברשימות שטוחות שניתן לגלול בהן, במקום בהיררכיות עמוקות.
החיסרון העיקרי של גלילה הוא חוסר הדיוק שלה. לעיתים רחוקות, גלילה מסתיימת בתצוגה של פסקה או משפט. המצב הזה בולט עוד יותר בתוכן שמחולק לדפים או לפריטים עם גבולות משמעותיים, כשהגלילה מסתיימת באמצע הדף או התמונה, כך שהם גלויים חלקית. בתרחישי השימוש האלה, חוויית הגלילה מבוקרת היטב.
מפתחי אתרים מסתמכים כבר זמן רב על פתרונות מבוססי JavaScript כדי לשלוט בגלילה ולטפל בבעיה הזו. עם זאת, פתרונות מבוססי JavaScript לא מספקים פתרון באיכות מלאה בגלל חוסר בפרימיטיבים של התאמה אישית של גלילה או גישה לגלילה מורכבת. CSS Scroll Snap מבטיח פתרון מהיר, באיכות גבוהה ובקל לשימוש, שפועל באופן עקבי בכל הדפדפנים.
CSS Scroll Snap מאפשר לכותבי אתרים לסמן כל מאגר גלילה באמצעות גבולות של פעולות גלילה שבהן צריך לסיים. לאחר מכן, הדפדפנים בוחרים את מיקום הסיום המתאים ביותר בהתאם לפרטים של פעולת הגלילה, לפריסה ולמידת הניראות של מאגר התמונות לגלילה ולפרטים של מיקומי הצמדה, ומבצעים אנימציה חלקה אליו. אם חוזרים לדוגמה הקודמת, כשהמשתמש מסיים לגלול בקרוסלה, התמונה הגלויה שלה נצמדת למיקום שלה. אין צורך לבצע התאמות גלילה ב-JavaScript.
CSS Scroll Snap
התכונה 'הצמדה לגלילה' מאפשרת לשנות את ההיסט של הגלילה בתוך מאגר גלילה כדי להגיע למיקום הצמדה מועדף בסיום פעולת הגלילה.
אפשר להשתמש בנכס scroll-snap-type
כדי להביע הסכמה לשימוש ב-snapping בזמן גלילה בקונטיינר. כך הדפדפן יידע שצריך לשקול להצמיד את מאגר הגלילה הזה למיקומי הצמדה שנוצרו על ידי הצאצאים שלו. scroll-snap-type
קובע את הציר שבו מתבצע הגלילה: x
, y
או both
, ואת מידת הקפדנות של הצמדת התמונה: mandatory
, proximity
. בהמשך נסביר על האפשרויות האלה.
כדי ליצור מיקום הצמדה, מגדירים את היישור הרצוי לאלמנט.
המיקום הזה הוא ההיסט בגלילה שבו מאגר הגלילה של האב הקרוב ביותר והרכיב מיושרים כפי שצוין לציר הנתון. אפשר לבצע את ההתאמות הבאות בכל ציר: start
, end
, center
.
כשהרכיב מיושר לפי start
, החלק הקדמי של אזור הצמדת הרכיב צריך להיות באותו קו עם החלק הקדמי של אזור הצמדת מאגר התמונות. באופן דומה, ההתאמות end
ו-center
מציינות שקצהו או מרכזו של חלון הצפייה בפריטים צריכים להיות באותו קו עם קצהו או מרכזו של אזור הצמדת הרכיבים.
הדוגמאות הבאות ממחישות איך להשתמש במושגים האלה.
דוגמה: גלריה אופקית
תרחיש לדוגמה נפוץ לשימוש ב-snapping בזמן גלילה הוא קרוסלה של תמונות. לדוגמה, כדי ליצור קרוסלה של תמונות אופקית שמתמקדת בכל תמונה בזמן הגלילה, אפשר לציין בקונטיינר הגלילה את הערך 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>
מכיוון שמיקומי הצמדה משויכים לאלמנט, אלגוריתם הצמדה יכול לקבוע בצורה חכמה מתי ואיך הוא יתבצע, בהתאם לאלמנט ולגודל של מאגר הגלילה. לדוגמה, נניח שתמונה אחת גדולה יותר מקרוסלה. אלגוריתם פשוט של הצמדה עשוי למנוע מהמשתמש להזיז את התמונה כדי לראות אותה במלואה. אבל במפרט נדרש שההטמעות יזהו את המקרה הזה ויאפשרו למשתמש לגלול בחופשיות בתוך התמונה, רק עם הצמדה לקצוות שלה.
דוגמה: דף מוצר עם תהליך רכישה
מקרה נפוץ נוסף שבו כדאי להשתמש ב-Snap to Scroll הוא דפים עם כמה קטעים לוגיים שאפשר לגלול ביניהם אנכית, למשל דף מוצר רגיל. 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, שמשמש לחישוב ההתאמות של הצמדת הגלילה. הנכס מגדיר את ההכנסה (inset) ביחס לתיבת ה-padding של מאגר הגלילה. בדוגמה שלנו, הוספנו 15vh
מרווח פנימי נוסף בחלק העליון, שמורה לדפדפן להתייחס למיקום נמוך יותר, 15vh
מתחת לקצה העליון של מאגר הגלילה, כקצה ההתחלה האנכי שלו לצורך הצמדת גלילה. כשמפעילים את הצמדת הרכיב, קצה ההתחלה של רכיב היעד יימצא באותו קו עם המיקום החדש, כך שיישאר מקום מעל.
המאפיין scroll-margin
מגדיר את סכום ההזזה החוצה שמשמש להתאמת התיבה בפועל של יעד הצמדה, בדומה לאופן שבו scroll-padding
פועל בקונטיינר הגלילה של הצמדה.
יכול להיות ששמתם לב שבשני המאפיינים האלה לא מופיעה המילה snap
. הסיבה לכך היא שהן משנות בפועל את התיבה לכל פעולות הגלילה הרלוונטיות, ולא רק ממקמות את הגלילה. לדוגמה, Chrome מביאים אותם בחשבון כשמחשבים את גודל הדף לפעולות גלילה של דפים, כמו PageDown ו-PageUp, וגם כשמחשבים את כמות הגלילה לפעולה Element.scrollIntoView()
.
אינטראקציה עם ממשקי API אחרים לגלילה
DOM Scrolling API
הצמדת גלילה מתרחשת אחרי כל פעולות הגלילה, כולל פעולות שהופעלו על ידי סקריפט. כשמשתמשים בממשקי API כמו Element.scrollTo
, הדפדפן מחשב את מיקום הגלילה המיועד של הפעולה, ולאחר מכן מחיל את הלוגיקה המתאימה של הצמדה כדי למצוא את המיקום הסופי של הצמדה. לכן, אין צורך בסקריפט משתמש שיבצע חישובים ידניים לצורך הצמדה.
גלילה חלקה
גלילה חלקה קובעת את ההתנהגות של פעולת גלילה פרוגרמטית, בעוד ש-scroll snap קובע את היעד שלה. מכיוון שהם שולטים בהיבטים אורתוגונליים של גלילה, אפשר להשתמש בהם יחד והם משלימים זה את זה.
התנהגות גלילה מעבר לקצה
Overscroll behavior 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
, תמיד מסתיימים במיקום ההזזה המבוקש. יכול להיות שהתכונה 'הצמדה לגלילה' תשנה את הזזת הגלילה אחרי שהגלילה הפרוגרמטית תושלם. חשוב לזכור שזו לא הייתה הנחה טובה גם לפני ההוספה של 'הצמדה לגלילה', כי יכול להיות שהגלילה הופסקה מסיבות אחרות, אבל זה נכון במיוחד לגבי 'הצמדה לגלילה'.
עבודות עתידיות
חוויית הגלילה הייתה מוקד סקר שנערך לאחרונה על ידי צוות Chrome.
לפי תוצאות הסקר, יש כמה תחומים שצריך להשקיע בהם עבודה נוספת כדי לצמצם את הפער בין ספריות הפלאגין לבין CSS.
בעתיד נתמקד בנושא scroll-snap
, כולל:
- זמינות ותאימות של ממשקי API בדפדפנים שונים.
- לעבוד על ממשקי CSS API חדשים כמו
scroll-start
. - עבודה על אירועי JS חדשים כמו
snapChanged()
.