הצצה לתהליך ולכלים ששימשו ליצירת חוויית Designcember בסגנון של יומן חגים.
ברוח חודש דצמבר וביומנים הרבים שמשתמשים בהם כדי לספור לאחור ולחגוג, רצינו להדגיש תוכן מהאינטרנט מהקהילה ומצוות Chrome. בכל יום הדגשנו פריט אחד של תוכן שקשור לפיתוח ממשק משתמש ולעיצוב, בסך 31 פריטים. בין הפריטים האלה היו 26 אתרי הדגמה, כלים, הודעות, פודקאסטים, סרטונים, מאמרים ומחקרים חדשים.
אפשר לראות את החוויה המלאה בכתובת designcember.com.
סקירה כללית
המטרה שלנו הייתה לספק חוויית אינטרנט נגישה, מודרנית, רספונסיבית וחיננית, בשימוש בפחות בייטים ככל האפשר. רצינו להדגיש ממשקי API חדשים ותואמים למגוון מסכים, כמו שאילתות בקונטיינרים, וגם לכלול דוגמה יפה למצב כהה באתר שמתמקד בעיצוב ובעל הרבה נכסים. כדי לעשות זאת, דחסנו את הקבצים, הצגנו כמה פורמטים, השתמשנו בכלי build שעברו אופטימיזציה ליצירת אתרים סטטיים, השקנו polyfill חדש ועוד.
מתחיל בתעלומה
הרעיון מאחורי האתר של יומן Designcember היה להציג בו את כל העבודות שרצינו להבליט במהלך חודש דצמבר, תוך שימוש בו כאתר הדגמה. החלטנו לבנות בניין דירות רספונסיבי שיכול להיות גבוה וצר יותר, או קצר ורחב יותר, עם חלונות שמתארגנים מחדש בתוך המסגרת. כל חלון ייצג יום אחד (ולכן, קטע תוכן אחד). עבדנו עם המאיירת Alice Lee כדי להפוך את החזון שלנו למציאות.
אליס הייתה מעוררת השראה, ושיתפה תהליכים ורישומים שהיו מעניינים גם ברעיונות המוקדמים שלהם. בזמן שהיא עבדה על הגרפיקה, אנחנו עבדנו על הארכיטקטורה. בדיונים הראשונים התמקדו בפריסת המאקרו, במבנה ובחלונות שלו. איך החלונות יתאימו לעמודה אחת, שתיים או שלוש ככל שיהיו יותר שטחי תצוגה זמינים? עד כמה הם יכולים להתכווץ או להתמתח? מה יהיה הגודל המקסימלי של הבניין? כמה החלונות יזוזו?
לפניכם תצוגה מקדימה של אב טיפוס רספונסיבי באמצעות grid-auto-flow: dense
, שמראה איך החלונות יכולים להיות ממוקמים באופן אוטומטי על ידי אלגוריתם התצוגה. מהר מאוד הבנו שרשתות של יחס גובה-רוחב הניבו ביצועים מיטביים כתצוגה אומנותית, אבל לא סופקו הזדמנות לאפשר לחלונות לגדול ולהצטמצם לשטח זמין לא אחיד ולהציג את העוצמה של שאילתות בקונטיינרים.
ברגע שהרשת הכללית הייתה יציבה יחסית והעניקה תובנות לגבי יכולת התגובה של הבניין והחלונות שלו, יכולנו להתמקד בחלון אחד. חלק מהחלונות התארכו, התכווצו, התכווצו, התרחבו והתאימו את עצמם מחדש יותר מאחרים בתצוגה.
כל חלון יצטרך להתמודד עם כמות מסוימת של תנודות בגודל. בהמשך מוצג אב טיפוס של חלון שמראה את התגובה שלו לתנודות, ומראה עד כמה אפשר לצפות שכל חלון אינטראקטיבי יתאים את עצמו.
אנימציה של חלונות באמצעות גיליונות פריימים
בחלק מהחלונות יש אנימציות כדי להוסיף אינטראקציה לחוויה. האנימציות נוצרות ביד, פריים אחרי פריים, ב-Photoshop. כל פריים מיוצא, הופך ל-Spritesheet באמצעות מחולל ה-spritesheet הזה, ואז עובר אופטימיזציה באמצעות Squoosh. לאחר מכן, אנימציית ה-CSS משתמשת ב-background-position-x
וב-animation-timing-function
, כפי שמוצג בדוגמה הבאה.
.una
background: url("/day1/una_sprite.webp") 0% 0%;
background-size: 400% auto;
}
.day:is(:hover, :focus-within) .una {
animation: una-wave .5s steps(1) alternate infinite;
}
@keyframes una-wave {
0% { background-position-x: 0%; }
25% { background-position-x: 300%; }
50% { background-position-x: 200%; }
75% { background-position-x: 100%; }
}
אנימציות מסוימות, כמו חביתת הכסף של היום השישי, היו אנימציות CSS מבוססות-שלבים.
השגנו את האפקט הזה באמצעות טכניקה דומה, באמצעות steps()
, עם ההבדל שהנקודות העיקריות היו מיקומי טרנספורמציה של CSS במקום מיקומי רקע.
אנונימיזציה של שירותי CSS
לחלק מהחלונות היו צורות ייחודיות. השתמשנו במסכות וב-aspect-ratio
כדי ליצור חלון גמיש, בעל צורה ייחודית ומתאים לעיצוב.
כדי ליצור מסכה, כמו זו של חלון שמונה, נדרשו כמה מיומנויות קלאסיות ב-Photoshop, וגם קצת ידע על האופן שבו מסכות פועלות באינטרנט. נבחן את החלון של היום השמיני.
כדי להפוך למסכה, צריך לבודד את הצורה הפנימית מסוג תלתן בעל ארבעה עלים ולמלא אותה בצבע לבן. הצבע הלבן מאפשר ל-CSS לקבוע איזה תוכן יישאר ואיזה תוכן לא יישאר. ב-Photoshop, החלק הפנימי של החלון נבחר ונוצרו בפיקסל אחד (כדי להסיר בעיות שקשורות ליצירת כינוי), ולאחר מכן בוצע מילוי לבן וייצוא באותו גובה ורוחב כמו מסגרת החלון. כך אפשר להציב את המסגרת ואת המסכה בשכבות זו על גבי זו, ולהציג את התוכן הפנימי בתוך המסגרת כצפוי.
בסיום, תוכלו לשנות את התוכן של החלון והוא תמיד יופיע בתוך המסגרת בהתאמה אישית. בתמונה הבאה מוצגת גרסת המצב הכהה של החלון, עם שיפוע רקע שונה ומסנן CSS זוהר שמופעל על התאורה.
אנו תומכים גם בחלונות רספונסיביים מבוססי שאילתות בקונטיינרים. בחלון תשע, יש דמות שמסתתרת מאחורי מסכה עד שהחלון מוצג בגודל צר יותר. כדי לוודא שהמשתמש לא יוכל לשנות את התמונה כך שהדמות תצא מהפריים, עינת השלימה עבורנו את הדמות במלואה. הדמות ממוסתרת בתוך החלון, אבל הצמחים לא, ולכן אחד האתגרים שטיפלנו בהם היה להוסיף שכבות של רכיבים מוסתרים לשכבות לא מוסתרות, ולוודא שהכול יתאים יחד.
בתמונה הזו אפשר לראות איך התמונה נראית בלי המסכה על החלון ועל הדמות.
דחיפת התמונה
כדי לשמור על איכות האיור ולהבטיח שחוויית המשתמש במסכים ברזולוציה גבוהה לא תהיה מטושטשת, עינת עבדה ביחס פיקסלים של 3x. התכנון היה להשתמש ב-imgix ולהציג תמונות ופורמטים שעברו אופטימיזציה בשרת שלהם, אבל גילינו ששינוי ידני באמצעות הכלי Squoosh יכול לחסוך לנו 50% או יותר.
איור מציב אתגרים ייחודיים לדחיסה, במיוחד בזכות הבריש והסגנון של אליס עם הקצוות השקופים והמחוספסים. בחרנו להשתמש ב-Squoosh כדי לדחוס כל תמונה בפורמט PNG בגודל 3x שמיוצאת מ-Photoshop, לתמונות קטנות יותר בפורמטים PNG, WebP ו-AVIF. לכל סוג קובץ יש יכולות דחיסה מיוחדות משלו, ונדרשו לנו יותר מ-50 תמונות כדי למצוא כמה הגדרות אופטימיזציה נפוצות.
ה-Squoosh CLI הפך להכרחית עם יותר מ-200 תמונות לביצוע אופטימיזציה – ביצוע כל הפעולות האלה באופן ידני היה נמשך כמה ימים. אחרי שהיו לנו את הגדרות האופטימיזציה המשותפות, העברנו אותן כהוראות בשורת הפקודה, והעברנו תיקיות שלמות של תמונות PNG שעובדו באצווה למקבילים שלהן דחוסים ב-WebP וב-AVIF.
זוהי דוגמה לפקודת squoosh ב-CLI של AVIF:
npx @squoosh/cli --quant '{"enabled":true,"zx":0,"maxNumColors":256,"dither":1}' --avif '{"cqLevel":19,"cqAlphaLevel":17,"subsample":1,"tileColsLog2":0,"tileRowsLog2":0,"speed":6,"chromaDeltaQ":false,"sharpness":5,"denoiseLevel":0,"tune":0}' image-1.png image-2.png image-3.png
אחרי שהוספת הגרפיקה האופטימיזציה למאגר, אפשר להתחיל לטעון אותה מ-HTML:
<picture>
<source srcset="/day1/inner-frame.avif" type="image/avif">
<source srcset="/day1/inner-frame.webp" type="image/webp">
<img alt="" decoding="async" role="presentation" src="/day1/inner-frame.png">
</picture>
כתיבת קוד המקור של התמונות הייתה חזרה על עצמה, לכן יצרנו רכיב Astro להטמעת תמונות באמצעות שורת קוד אחת.
<Pic filename="day1/inner-frame" role="presentation" />
משתמשים בקורא מסך ובמקלדת
חלק גדול מחוויית Designcember מתבסס על האמנות והחלונות האינטראקטיביים. חשוב לנו שמשתמשים עם מקלדת יוכלו להשתמש באתר ולהציץ בחלונות, ושמשתמשים בקורא מסך ייהנו מחוויה נעימה עם קריינות.
לדוגמה, כשהטמענו את התמונות, השתמשנו ב-role="presentation"
כדי לסמן את התמונה כתמונה חזותית לקוראי מסך. לדעתנו, חוויית המשתמש תהיה גרועה אם יהיו 5 עד 12 תיאורים מקוטעים של alt
. לכן, סימנו את התמונות כתמונות להצגה וסיפקנו קריינות כללית על החלון. כשעוברים בין החלונות של קורא המסך מקבלים תחושת עלילה נחמדה, שקיוויתנו להעביר את הכיף והקפצה באתר שרוצים לשתף.
בסרטון הבא מוצגת הדגמה של חוויית השימוש במקלדת. המקשים Tab, Enter, מקש הרווח ומקש Escape משמשים לתזמור את המיקוד בחלון הקופץ והחלונות ומהם.
חוויית השימוש עם קורא המסך כוללת מאפייני ARIA מיוחדים שמבהירים את התוכן. לדוגמה, בקישור ליום מסוים כתוב רק 'יום אחד' או 'יום שני', אבל עם הוספת קצת ARIA, הקריינות תהיה 'יום אחד' ו'יום שני'. בנוסף, כל התמונות מסוכמות בתווית אחת, כך שלכל חלון יש תיאור.
מחולל אתרים מבוסס-רכיבים, סטטי תחילה,
Astro עזר לצוות לעבוד יחד בקלות על האתר. מודל הרכיב היה מוכר גם למפתחים של Angular וגם למפתחים של תגובה, אבל מערכת סגנון שם המחלקה בהיקף עזרה לכל מפתח לדעת שהעבודה שלו על חלון לא הייתה מתנגשת עם אף אחד אחר.
ימים כרכיבים
כל יום היה רכיב שאחזר סטטוס ממאגר נתונים של זמן build. כך אנחנו יכולים להריץ את הלוגיקה של התבנית לפני שה-HTML מגיע לדפדפן. הלוגיקה תקבע אם צריך להציג הסבר קצר ביום מסוים, כי ימים לא פעילים אין חלונות קופצים.
גרסאות ה-build מריצים מדי שעה, ומאגר הנתונים של זמני ה-build ייפתח ביום חדש כששרת ה-build יהיה אחרי חצות. המערכות הקטנות האלה מתעדכנות באופן עצמאי ומספקות את כל מה שדרוש כדי שהאתר יהיה עדכני.
סגנונות ברמת ההיקף ו-Open Props
ב-Astro הסגנונות שנכתבים בתוך מודל הרכיבים ממופים, כך שקל יותר לחלק את עומס העבודה בין חברי צוות רבים, וגם כיף להשתמש ב-Open Props. הסגנונות של Open Props normalize.css עזרו לנו עם העיצוב המותאם (בהיר וכהה), וגם עזרו לנו להתמודד עם תוכן כמו פסקאות וכותרות.
בתחילת הדרך של Astro, נתקלנו בכמה בעיות עם PostCSS. לדוגמה, לא הצלחנו לעדכן לגרסה האחרונה של Astro בגלל יותר מדי בעיות ב-build. אפשר להקדיש זמן רב יותר לנושא הזה, ולבצע אופטימיזציה של תהליכי העבודה של ה-build והמפתחים.
קונטיינרים גמישים
חלק מהחלונות מתרחבים ומתכווצים, תוך שמירה על יחס גובה-רוחב כדי לשמור על הגרפיקה שלהם. השתמשנו בחלונות נוספים כדי להמחיש את העוצמה של ארכיטקטורה מבוססת-רכיבים עם שאילתות בקונטיינרים. שאילתות בקונטיינרים אפשרו לחלונות להכיל מידע ספציפי לגבי עיצוב רספונסיבי, ולהתאים את עצמם על סמך הגדלים שלהם. חלק מהחלונות עברו מצר לרחבים, ולכן היה צריך לשנות את גודל המדיה שבתוכם ואת המיקום שלה.
ככל שיהיו יותר שטחים פנויים לחלון, נוכל לשנות את הגודל או את רכיבי הצאצאים של החלון כדי להתאים אותו. התברר ששאילתות מאגר הן לא רק דרך מעניינת להציג חלונות מותאמים, אלא הן נדרשות כדי לאפשר תזמון פשוט יותר של פריסות מסוימות.
.day {
container: inline-size;
}
.day > .pane {
min-block-size: 250px;
@container (min-width: 220px) {
min-block-size: 300px;
}
@container (min-width: 260px) {
min-block-size: 310px;
}
@container (min-width: 360px) {
min-block-size: 450px;
}
}
הגישה הזו שונה מהשמירה על יחס גובה-רוחב. הוא מספק יותר שליטה והזדמנויות נוספות. בגודל מסוים, ילדים רבים עוברים ממקום למקום כדי להסתגל לפריסה חדשה.
שאילתות בקונטיינרים גם אפשרו לנו לתמוך בקונטיינרים בכיוון אנכי, כך שככל שהחלון התארך, יכולנו לשנות את הסגנונות שלו כך שיתאימו. ניתן לראות זאת בשאילתות שמבוססות על גובה, שבהן השתמשנו בנפרד, ובנוסף לשאילתות שמבוססות על רוחב:
.person {
place-self: flex-end;
margin-block: 25% 50%;
margin-inline-start: -15%;
z-index: var(--layer-1);
@container (max-height: 350px) and (max-width: 425px) {
place-self: center flex-end;
inline-size: 50%;
inset-block-end: -15%;
margin-block-start: -2%;
margin-block-end: -25%;
z-index: var(--layer-2);
}
}
השתמשנו גם בשאילתות של קונטיינרים כדי להציג ולהסתיר פרטים, ככל שהאומנות נעשתה צפופה יותר בגדלים קטנים יותר ותחלץ בגדלים רחבים יותר. חלון תשע הוא דוגמה נהדרת לאופן שבו זה נכנס לתוקף:
תמיכה בדפדפנים שונים
כדי ליצור חוויה מודרנית נהדרת בדפדפנים שונים, במיוחד לממשקי API ניסיוניים כמו שאילתות בקונטיינרים, אנחנו צריכים polyfill מצוין. שלחנו קריאה לצוות שלנו, ו-Surma עמדה בראש פיתוח של גרסת polyfill חדשה של שאילתות קונטיינר. הפוליפיל מבוסס על ResizeObserver, MutationObserver ועל הפונקציה :is() ב-CSS. לכן, כל הדפדפנים המודרניים תומכים ב-polyfill, במיוחד Chrome ו-Edge מגרסה 88, Firefox מגרסה 78 ו-Safari מגרסה 14. השימוש ב-polyfill מאפשר להשתמש בכל אחד מהתחבירים הבאים:
/* These are all equivalent */
@container (min-width: 200px) {
/* ... */
}
@container (width >= 200px) {
/* ... */
}
@container size(width >= 200px) {
/* ... */
}
מצב כהה
עוד טאצ' אחרון שהיה חיוני לאתר של Designcember היה עיצוב כהה יפהפה. רצינו להראות איך אפשר להשתמש באמנות עצמה כדי להיות שותפים פעילים ביצירת חוויה מעולה במצב כהה. לשם כך, שינינו את סגנונות הרקע של כל חלון באופן פרוגרמטי, והשתמשנו ב-CSS כמה שאפשר כשיצאנו את הגרפיקה של החלון. רוב הרקעים היו פסילות CSS, כדי שיהיה קל יותר לשנות את ערכי הצבעים שלהם. לאחר מכן הנחנו את הגרפיקה מעליהם.
ביצי פסחא נוספות
נגיעות אישיות
הוספנו כמה נגיעות אישיות לדף כדי להוסיף לאתר יותר אישיות. החלק הראשון היה צוות הדמויות, שנוצר בהשראת הצוות שלנו. הוספנו גם סמן בסגנון רטרו בימים שבהם לא הייתה פעילות, וניסינו כמה סגנונות של סמל דף הבית.
נגיעות פונקציונליות
אחת מהתכונות הפונקציונליות הנוספות היא האפשרות 'מעבר ל'היום', עם ציפור שפוגעת בראש הבניין. לחיצה על הציפור או הקשה על מקש Enter תעביר אתכם למטה בדף אל היום הנוכחי בחודש, כדי שתוכלו להגיע במהירות להשקות האחרונות.
באתר Designcember.com יש גם גיליון מיוחד של סגנונות עיצוב להדפסה, שבו אנחנו למעשה מציגים תמונה ספציפית שמתאימה במיוחד לנייר בגודל 21.6 x 27.9 ס"מ, כדי שתוכלו להדפיס את היומן בעצמכם ולשמור על האווירה החגיגית כל השנה.
בסך הכול, השקענו המון עבודה כדי ליצור חוויית אינטרנט מודרנית, מהנה וחיננית, כדי לחגוג את פיתוח ממשק המשתמש במשך כל חודש דצמבר. אנחנו מקווים שנהניתם!