אתר אחד, שני כיווני קריאה, שלוש רמות תנועה: איך בניתי את idanach.com
איך האתר שלי מעיף את אותיות השם אל הלוגו במחשב חזק, נשאר דומם למי שביקש פחות תנועה, ונקרא בדיוק אותו דבר גם בעברית.
האתר שלי נפתח בשם שלי, בתוך מסלול הקפה של קטעי וידאו מהפרויקטים שמסתובב סביבו לאט. כשגוללים, אותיות השם עפות למעלה אל הלוגו שבכותרת. במחשב נייד חזק זה העמוד הכי מונפש שבניתי. למי שביקש מהמכשיר שלו פחות תנועה, אותו עמוד נשאר דומם לגמרי. ובעברית זה שוב אותו עמוד, שנקרא מימין לשמאל, והאותיות נוחתות בלוגו שבצד השני.
בפוסט הזה אספר איך עמוד אחד עושה את כל זה, ועל מה הייתי צריך לוותר כדי שהוא יישאר אמיתי.
הבעיה
אני רוצה שמעסיקים יכירו אותי כמי שבונה מערכות שלמות ויש לו גם עין לעיצוב. תיק עבודות הוא המקום היחיד שבו אפשר להראות את שני הצדדים יחד, ולכן הוא היה חייב להיות יוצא דופן ומעוצב בקפידה. אבל דווקא ב“יוצא דופן” תיקי עבודות נוטים להשתבש:
- מנועי חיפוש ועוזרי AI צריכים לקרוא אותו. עמוד שמצייר את הטקסט שלו בסקריפט, או מסתיר אותו עד שאנימציה מסתיימת, לא אומר להם כלום.
- שתי שפות, שני כיווני קריאה. אנגלית ב-
/, עברית ב-/he/. העברית היא לא תרגום שהודבק לאותו מבנה עמוד: היא נקראת בכיוון ההפוך, וכל חץ, כל שוליים וכל אנימציה צריכים לדעת את זה. - לא כל מכשיר הוא מחשב חזק. טלפון ברשת איטית, מחשב ישן או מבקר שהפעיל הפחתת תנועה צריכים לקבל עמוד שלם, לא עמוד שבור.
- הוא חייב להיות מהיר, כי גם תיק עבודות איטי אומר משהו.
מה ניסיתי קודם
הרעיון הראשון שלי לפתיחה היה דיוקן שלי שמורכב מחלקיקים. הוא נראה טוב, אבל היה קרוב מדי לתיק עבודות של מישהו אחר שאני מעריך. אתר אישי ששואל את החתימה של מישהו אחר הוא לא באמת אישי, אז ויתרתי עליו.
הכיוון שנשאר הגיע מהגלילה באתר getartcraft.com, שאהבתי: אריחים שמסתובבים סביב כותרת, אותיות שעפות אל הלוגו, ותוכן עניינים של פרקים לאורך סרגל. בניתי גרסה משלי כאב-טיפוס, עם מסכים אמיתיים מהפרויקטים שלי, לולאות של חמש שניות מסרטוני ההדגמה שלי ותמונת שער צבעונית לכל פרויקט. רק כשהייתי שלם עם אב-הטיפוס התחלתי לבנות את האתר עצמו. הבדיקות של האתר עוברות על העמודים המרכזיים שלו בשבעה רוחבי מסך, מ-1920 ועד 360 פיקסלים.
מה עבד
קודם התוכן
האתר בנוי ב-Astro כ-HTML סטטי רגיל. כל מילה, בשתי השפות, נמצאת בעמוד עוד לפני שרץ סקריפט כלשהו. התנועה מתווספת מעל התוכן, ואף פעם לא נושאת אותו.
מסלול ההקפה הוא דוגמה טובה. ה-<h1> של העמוד הוא תמיד השם האמיתי שלי, ככותרת רגילה אחת. האותיות המעופפות הן עותק
לקישוט בלבד, שמוסתר מקוראי מסך בעזרת aria-hidden. גם אם הסקריפט לא רץ בכלל, רואים את השם, את השורה שמתחתיו ואת
כל הפרויקטים.
שלוש רמות תנועה, שנקבעות לפני שהעמוד מצויר
סקריפט קטן שמוטמע ב-<head> רץ לפני שמשהו מצויר על המסך, ובוחר רמה:
function detect() {
if (mm('(prefers-reduced-motion: reduce)')) return ['still', 'reduce'];
var c = navigator.connection || {};
if (c.saveData) return ['light', 'save-data'];
if (/(^|-)2g|3g/.test(c.effectiveType || '')) return ['light', 'slow-network'];
if ((navigator.deviceMemory || 8) <= 2) return ['light', 'low-memory'];
if ((navigator.hardwareConcurrency || 8) <= 2) return ['light', 'few-cores'];
if (get('sessionStorage', 'idanach-lowfps') === '1') return ['light', 'low-fps'];
var g = gpu(); // no WebGL, or a software renderer
if (g !== 'ok') return ['light', g];
return ['full', 'capable'];
}
- מלאה: מסלול ההקפה עם וידאו חי, הטיה לפי תנועת העכבר, מעוף האותיות, גלילה חלקה (לא במסכי מגע), סליל הפרויקטים הנעוץ ומעברי תמונה בין עמודים.
- קלה: מסלול ההקפה עם תמונות סטילס, הופעות פשוטות וגלילה רגילה, ואף סרטון לא מתנגן מעצמו. מכשיר שמציג את השניות הראשונות בפחות מ-40 פריימים בשנייה עובר לרמה הקלה מעצמו.
- בלי תנועה: שום דבר לא זז. מסלול ההקפה הופך לקולאז’ סטטי, והכול קריא.
התוצאה נכתבת על אלמנט ה-<html> לפני שהעמוד מצויר, כך שהגרסה הלא נכונה לא מהבהבת אף לרגע. מתג קטן בתחתית העמוד
(ובטלפון, בתפריט), “תנועה: אוטומטי / מלאה / קלה / כבויה”, מאפשר לשנות את הבחירה, והאתר זוכר אותה. התוכן זהה בכל
הרמות; רק התנועה משתנה.
גיליון סגנונות אחד, שני כיוונים
כל מבנה העמודים בנוי על מאפיינים לוגיים של CSS: margin-inline-start במקום margin-left, ו-inset-inline-end
במקום right. גיליון סגנונות אחד משרת את שני הכיוונים, והעמודים בעברית מתהפכים מעצמם בלי מערכת כללים נוספת.
בדברים המעטים שאינם קשורים למבנה העמוד אני מטפל ביד: בעברית סליל הפרויקטים זז לכיוון השני, והאותיות המעופפות
נוחתות בלוגו שמימין.
גם הטיפוגרפיה דרשה פתרון משלה. העמודים באנגלית כתובים ב-Schibsted Grotesk, עם Instrument Serif נטוי למילים מודגשות. בעברית אין אותיות נטויות, ולכן העמודים בעברית כתובים ב-Heebo, והמילים המודגשות עוברות ל“גברת לוין”, גופן עברי בכתב יד. בשתי השפות צבע ההדגשה הוא שמבליט אותן, כך שהעיצוב אומר אותו דבר בשני הכתבים.
הגופנים מאוחסנים באתר עצמו, ורובם מחולקים לתת-קבוצות בעזרת unicode-range, כך שהדפדפן מוריד רק את קבוצות האותיות
שהעמוד באמת צריך. “גברת לוין” היא היוצאת מן הכלל: הרישיון שלה לא מאפשר לשנות את הקובץ, ולכן הוא מוגש בדיוק כמו שהוא,
ו-unicode-range רק מגביל אותו לאותיות עבריות. רק הגופן הראשי נטען מראש.
מעברים בין עמודים, רק איפה שהם עוזרים
לחיצה על כרטיס פרויקט בעמוד הבית מגדילה את התמונה שלו עד שהיא הופכת לתמונה הראשית של עמוד הפרויקט, בעזרת View Transitions בין מסמכים. שני כללים מונעים תקלות: המעבר רץ רק ברמה המלאה, ומכיוון שאותו פרויקט מופיע כמה פעמים בעמוד הבית, שם המעבר ניתן רק לתמונה שלחצתם עליה ולתמונה התואמת לה בעמוד הבא. דפדפנים בלי View Transitions פשוט טוענים את העמוד הבא.
להסביר למנועי חיפוש מי אני
לכל עמוד יש כתובת קנונית שמפנה אליו עצמו, וקישורי hreflang הדדיים בין הגרסה האנגלית לעברית. הנתונים המובנים
מתארים אדם אחד, עם השם שלי באנגלית, Idan Achrak, והשם בעברית כשם חלופי. תמונות השיתוף מרונדרות בדפדפן אמיתי, ולפני
הצילום, המרנדר בודק שהגופן העברי באמת מצייר את האותיות, כך שקישור בעברית שמשתפים אף פעם לא מציג ריבועים ריקים.
המלכודת: בדיקה ששיקרה לגבי המהירות
המעבר האוטומטי מתנועה מלאה לקלה עבד קצת יותר מדי טוב. בדפדפן המדומה שבו בדקתי, השניות הראשונות רצו בפחות מ-40 פריימים בשנייה, אז האתר עבר בשקט לרמה הקלה, ואני בדקתי גרסה שמבקרים אמיתיים במחשב נייד לא יראו לעולם. Chrome בלי ממשק, שבו משתמשים כלי מדידת המהירות, עושה בדיוק אותו דבר.
הפתרון היה לאפשר לבדיקה לבחור את הרמה. כתובת עם ?motion=full כופה רמה לטעינה אחת של העמוד בלי לשמור אותה,
ובדיקות המהירות רצות פעמיים: פעם ברמה המלאה בכפייה, ופעם ברמה הקלה.
מה נמדד
מדדתי את האתר החי בבדיקת המובייל של Lighthouse, שמדמה טלפון בינוני בחיבור 4G איטי. לעמוד הבית, לעמוד האודות ולסיפור פרויקט אחד, באנגלית ובעברית, ברמה המלאה וברמה הקלה:
- Largest Contentful Paint: 2.8 עד 3.3 שניות (תקציב: עד 3.5 שניות)
- Cumulative Layout Shift: 0 בכל העמודים (תקציב: עד 0.1)
- JavaScript בעמוד הבית: 92 KB ברמה המלאה, 44 KB ברמה הקלה (תקציב: פחות מ-150 KB)
מספר אחד כבר יש לי, של התמונות. הן מתחילות כקובצי PNG ו-JPG בגודל מלא, וצינור התמונות של Astro הופך אותן ל-WebP ברוחבים שכל עמוד צריך. את הקבצים המקוריים Astro עדיין מעתיק לאתר הבנוי, ולכן שלב בבנייה מוחק כל תמונה שאף עמוד לא מפנה אליה: 348 קבצים, כ-90 MB. כך האתר הבנוי ירד מכ-170 MB לכ-80 MB.
מה הייתי עושה אחרת
הייתי בונה את האפשרות לבחור רמה בבדיקות עוד לפני האנימציה הראשונה, ולא אחרי שבדיקה הטעתה אותי. כל יכולת שמתאימה את עצמה למכשיר צריכה דרך לקבע אותה, אחרת כל מדידה מודדת בעצם את מכונת הבדיקה.
מי עשה מה
בניתי את האתר הזה עם Claude Code, בהכוונה שלי. הכיוון האמנותי, ההיפוך מימין לשמאל, רמות התנועה וההחלטה שכל תמונה וכל קטע וידאו יגיעו מהפרויקטים שלי, כל אלה שלי. בעמוד האודות יש קולופון קצר עם השאר.
מותר לשבור את ההדגמות: יומן ביטול שמחזיר כל הדגמה למצבה המקורי אחרי שלוש שעות