סקירה בסיסית על איך ליצור חוויה דומה לסטוריז באינסטגרם באינטרנט.
בפוסט הזה אני רוצה לשתף את החשיבה על בניית רכיב Stories לאינטרנט שהוא רספונסיבי, תומך בניווט באמצעות המקלדת ופועל בדפדפנים שונים.
אם אתם מעדיפים הדגמה מעשית של בניית רכיב הסטוריז בעצמכם, כדאי לעיין בCodelab של רכיב הסטוריז.
אם אתם מעדיפים לצפות בסרטון, הנה גרסת YouTube של הפוסט הזה:
סקירה כללית
שתי דוגמאות פופולריות לחוויית השימוש של סטוריז הן סנאפצ'ט סטוריז ואינסטגרם סטוריז (שלא לדבר על Fleets). במונחים כלליים של חוויית משתמש, סטוריז הם בדרך כלל תבנית לנייד בלבד, שמתמקדת בהקשה, לניווט בין כמה מינויים. לדוגמה, באינסטגרם, המשתמשים פותחים סטורי של חבר ועוברים על התמונות שבו. בדרך כלל הם עושים את זה עם הרבה חברים בו-זמנית. כשהמשתמש לוחץ על הצד השמאלי של המכשיר, הוא מדלג לסטורי הבא של אותו חבר. החלקה ימינה מדלגת לחבר אחר. רכיב Story דומה מאוד לקרוסלה, אבל מאפשר לנווט במערך רב-ממדי, בניגוד למערך חד-ממדי. זה כאילו יש קרוסלה בתוך כל קרוסלה. 🤯
קרוסלה שנייה של סטוריז "בערימה"
👍 רשימה בתוך רשימה, כלומר: מערך רב-ממדי
בחירת הכלים המתאימים למשימה
בסך הכול, היה די פשוט לבנות את הרכיב הזה, בזכות כמה תכונות קריטיות של פלטפורמת האינטרנט. בואו נכסה אותם!
רשת CSS
הפריסה שלנו לא הייתה משימה קשה מדי עבור CSS Grid, כי יש לה כמה דרכים יעילות לטפל בתוכן.
פריסת חברים
רכיב ה-wrapper הראשי של .stories הוא תצוגת גלילה אופקית שמותאמת לניידים:
.stories {
inline-size: 100vw;
block-size: 100vh;
display: grid;
grid: 1fr / auto-flow 100%;
gap: 1ch;
overflow-x: auto;
scroll-snap-type: x mandatory;
overscroll-behavior: contain;
touch-action: pan-x;
}
/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
max-inline-size: 480px;
max-block-size: 848px;
}
בואו נפרק את הפריסה של grid:
- אנחנו ממלאים באופן מפורש את אזור התצוגה בנייד באמצעות
100vhו-100vwומגבילים את הגודל במחשב /מפריד בין תבניות השורות והעמודות שלנוauto-flowמתורגם ל-grid-auto-flow: column- תבנית הזרימה האוטומטית היא
100%, שבמקרה הזה היא רוחב חלון הגלילה
בטלפון נייד, אפשר לחשוב על זה כאילו גודל השורה הוא גובה אזור התצוגה וכל עמודה היא רוחב אזור התצוגה. נמשיך עם הדוגמה של Snapchat Stories ו-Instagram Stories, כל עמודה תהיה סטורי של חבר. אנחנו רוצים שהסטוריז של החברים ימשיכו מעבר לאזור התצוגה, כדי שיהיה לאן לגלול. הגריד ייצור כמה עמודות שצריך כדי לפרוס את ה-HTML של כל סטורי של חבר, וייצור עבורנו קונטיינר דינמי ורספונסיבי לגלילה. התצוגה הזו אפשרה לנו לרכז את כל האפקט.
מקבצים
לכל חבר אנחנו צריכים את הסטוריז שלו במצב שמוכן לעימוד. כדי להתכונן לאנימציה ולדפוסים מהנים אחרים, בחרתי בערימה. כשאני אומרת "ערימה", הכוונה היא כמו שמסתכלים על כריך מלמעלה, ולא מהצד.
באמצעות רשת CSS, אנחנו יכולים להגדיר רשת של תא אחד (כלומר ריבוע), שבה השורות והעמודות חולקות כינוי ([story]), ואז כל צאצא מוקצה למרחב של התא היחיד עם הכינוי:
.user {
display: grid;
grid: [story] 1fr / [story] 1fr;
scroll-snap-align: start;
scroll-snap-stop: always;
}
.story {
grid-area: story;
background-size: cover;
…
}
כך ה-HTML שלנו שולט בסדר הערימה וגם שומר על כל הרכיבים בזרימה. שימו לב שלא היינו צריכים לעשות שום דבר עם המיקום של absolute או z-index, ולא היינו צריכים לתקן את התיבה עם height: 100% או width: 100%. הרשת הראשית כבר הגדירה את הגודל של אזור התצוגה של תמונת הסטורי, אז לא היה צריך להגדיר לאף אחד מהרכיבים של הסטורי למלא אותו.
נקודות הצמדה לגלילה ב-CSS
המפרט של נקודות העצירה בגלילה ב-CSS מאפשר לנעול בקלות רכיבים באזור התצוגה בזמן הגלילה. לפני שהמאפיינים האלה של CSS היו קיימים, הייתם צריכים להשתמש ב-JavaScript, וזה היה… מסובך, בלשון המעטה. במאמר Introducing CSS Scroll Snap Points של שרה דרסנר (Sarah Drasner) יש הסבר מצוין על אופן השימוש בהן.
scroll-snap-points.
בלעדיו, המשתמשים יכולים לגלול בחופשיות כרגיל. הדפדפן מתעכב קצת על כל פריט.
.stories { display: grid; grid: 1fr / auto-flow 100%; gap: 1ch; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior: contain; touch-action: pan-x; }
.user { display: grid; grid: [story] 1fr / [story] 1fr; scroll-snap-align: start; scroll-snap-stop: always; }
בחרתי בנקודות הצמדה לגלילה מכמה סיבות:
- נגישות בחינם. לפי המפרט של נקודות העצירה בגלילה, לחיצה על המקשים חץ שמאלה וחץ ימינה אמורה להעביר את המשתמש בין נקודות העצירה כברירת מחדל.
- מפרט שמתפתח כל הזמן. המפרט של נקודות העצירה בגלילה מתעדכן כל הזמן בתכונות חדשות ובשיפורים, מה שאומר שרכיב הסטוריז שלי כנראה רק ישתפר מעכשיו והלאה.
- קלות ההטמעה. נקודות העצירה בגלילה נועדו בעיקר לשימוש בדפדוף אופקי שמתמקד במגע.
- אינרציה חופשית בסגנון פלטפורמה. בכל פלטפורמה הגלילה והעצירה יתבצעו בסגנון שלה, בניגוד לאינרציה מנורמלת שיכולה להיות בסגנון גלילה ועצירה מוזר.
תאימות לדפדפנים שונים
בדקנו את זה ב-Opera, ב-Firefox, ב-Safari וב-Chrome, וגם ב-Android וב-iOS. הנה סקירה קצרה של התכונות באינטרנט שבהן מצאנו הבדלים ביכולות ובתמיכה.
עם זאת, חלק מה-CSS לא הוחל, ולכן בחלק מהפלטפורמות חסרות כרגע אופטימיזציות של חוויית המשתמש. נהניתי מהעובדה שלא הייתי צריך לנהל את התכונות האלה, ואני בטוח שהן יגיעו בסופו של דבר לדפדפנים ולפלטפורמות אחרים.
scroll-snap-stop
קרוסלות היו אחד מהמקרים העיקריים של חוויית משתמש שהובילו ליצירת המפרט של נקודות עצירה (snap points) בגלילה ב-CSS. בניגוד לסטוריז, קרוסלה לא תמיד צריכה לעצור בכל תמונה אחרי שמשתמש יוצר איתה אינטראקציה. יכול להיות שזה בסדר או אפילו מומלץ לעבור במהירות על הקרוסלה. לעומת זאת, בסטוריז הכי טוב לנווט אחד אחרי השני,
וזה בדיוק מה ש-scroll-snap-stop מספק.
.user {
scroll-snap-align: start;
scroll-snap-stop: always;
}
נכון לזמן כתיבת הפוסט הזה, scroll-snap-stop נתמך רק בדפדפנים שמבוססים על Chromium. כאן אפשר לבדוק אם יש עדכונים לגבי תאימות לדפדפנים. אבל זה לא מונע את השימוש. זה רק אומר שבדפדפנים לא נתמכים, משתמשים יכולים לדלג בטעות על חבר. אז המשתמשים יצטרכו להיות זהירים יותר, או שנצטרך לכתוב קוד JavaScript כדי לוודא שחבר שדילגו עליו לא מסומן כמישהו שצפו בו.
אם אתם רוצים לדעת עוד, קראו את המפרט.
overscroll-behavior
קרה לכם פעם שגללתם במודל ופתאום התחלתם לגלול את התוכן שמאחורי המודל?
overscroll-behavior
מאפשר למפתח ללכוד את הגלילה הזו ולא לאפשר לה
לצאת. הוא מתאים לכל מיני אירועים. הרכיב My Stories משתמש בו כדי למנוע מתנועות החלקה וגלילה נוספות לצאת מהרכיב.
.stories {
overflow-x: auto;
overscroll-behavior: contain;
}
Safari ו-Opera היו שני הדפדפנים שלא תמכו בזה, וזה בסדר גמור. המשתמשים האלה יקבלו חוויית גלילה מעבר לקצה כמו שהם רגילים, ויכול להיות שהם לא ישימו לב לשיפור הזה. אני אישית מעריץ גדול של האפקט הזה, ואני אוהב לכלול אותו כחלק כמעט מכל תכונת גלילה מעבר לקצה שאני מטמיע. היא לא מזיקה ויכולה רק לשפר את חוויית המשתמש.
scrollIntoView({behavior: 'smooth'})
כשהמשתמש מקיש או לוחץ ומגיע לסוף קבוצת הסטוריז של חבר, הגיע הזמן לעבור לחבר הבא בקבוצת נקודות העצירה בגלילה (scroll snapping). באמצעות JavaScript, יכולנו להפנות לחבר הבא ולבקש לגלול אותו לתצוגה. התמיכה בפעולות הבסיסיות האלה מצוינת, וכל דפדפן גולל את האלמנט לתצוגה. אבל לא כל הדפדפנים עשו את זה 'smooth'. זה רק אומר שהיא נגללת לתצוגה במקום להצמיד אותה.
element.scrollIntoView({
behavior: 'smooth'
})
Safari היה הדפדפן היחיד שלא תמך ב-behavior: 'smooth' כאן. כאן אפשר לבדוק אם יש עדכונים לגבי תאימות לדפדפנים.
קורס מעשי
עכשיו, אחרי שאתם יודעים איך אני עשיתי את זה, איך אתם הייתם עושים את זה? בואו נגוון את הגישות שלנו ונלמד את כל הדרכים לבנות באינטרנט. צרו הדגמה, שלחו לי ציוץ עם הגרסה שלכם, ואוסיף אותה לקטע רמיקסים של הקהילה שבהמשך.
הרשאה לקהילה ליצור רמיקסים
- @geoffrich_ עם Svelte: קוד
- @GauteMeekOlsen עם Vue: הדגמה + קוד
- @AnaestheticsApp עם Lit: קוד