8 שלב בניית היכולות

View Transitions API — מעברי עמודים כמו אפליקציה

בפרק הזה תבינו למה אתר מרגיש כמו אתר — עם "קפיצות" חדות בין עמודים — ולמה אפליקציה מרגישה כמו אפליקציה (כל מעבר הוא אנימציה חלקה). View Transitions API סוגר את הפער הזה ב-CSS טהור, בלי framework, בלי ספרייה. תלמדו את שלושת סוגי המעברים — cross-fade (ברירת-מחדל), morph (אלמנט "עף" מעמוד לעמוד כמו App Store), ו-slide (החלקה בין עמודים); תדעו להבדיל בין same-document (SPA) ל-cross-document (MPA, Astro, אתרים סטטיים); ותקבלו 3 פרומפטים מדויקים ל-AI שמייצרים מעברים מקצועיים ב-3-10 שורות CSS — לא ב-200 שורות JavaScript.

מה יהיה לך בסוף הפרק הזה
מה תוכלו לעשות בסוף הפרק הזה
דרישות קדם
הפרויקט שלך

בפרק 7 הוספתם לאתר שלכם Scroll-Driven Animations — reveal בגלילה, progress bar, ו-parallax ב-CSS טהור. האתר כבר "חי" כשגוללים. אבל יש עדיין רגע אחד שחושף אותו כ"אתר" ולא כ"אפליקציה" — הניווט בין עמודים. לוחצים על קישור, המסך נהיה לבן לרגע, ואז עמוד חדש "קופץ". זה ה-hard page refresh הקלאסי. בפרק הזה (8) תסגרו את הפער האחרון: תוסיפו View Transitions API שהופך כל מעבר לאנימציה חלקה — cross-fade ב-3 שורות CSS, או morph של כרטיס מוצר שעף לעמוד הפריט כמו ב-App Store. בפרק הבא (9) — Glassmorphism, Liquid Glass, Aurora UI ומגמות עיצוב מודרניות — נעבור ל-שכבת האפקטים: backdrop-filter: blur(), mesh gradients, ו-Aurora backgrounds אנימטיים. אחרי פרק 9 יהיו לכם את כל השכבות: layout (פרק 5), modern CSS (פרק 6), scroll animations (פרק 7), page transitions (פרק 8), ו-visual effects (פרק 9) — החמישייה שהופכת אתר מ"בסדר" ל"וואו". פרק 8 הוא דרישת-קדם ל-capstone בפרק 13, שם תבנו design brief שכולל View Transitions כחלק מה-spec.

מילון מונחים — 10 מושגים חדשים בפרק
מונח (English)תרגוםהגדרה בשורה אחת
View Transitions APIממשק מעברי תצוגהAPI מקורי בדפדפן שמאפשר אנימציה חלקה בין שני מצבי DOM שונים — בתוך עמוד אחד (SPA) או בין עמודים (MPA)
view-transition-nameשם מעבר תצוגהCSS property שמסמן אלמנט כ"משתתף" במעבר; הערך חייב להיות ייחודי בכל רגע נתון
::view-transition (pseudo-elements)פסאודו-אלמנטים של המעבר7 שכבות וירטואליות שהדפדפן יוצר אוטומטית בזמן מעבר — אפשר לעצב אותן עם @keyframes
Cross-fadeמעבר הדרגתיברירת-המחדל: העמוד הישן נעלם ב-fade-out והחדש מופיע ב-fade-in, בדרך כלל ב-250ms
Morph Transitionמעבר מורפינג / Shared Elementאלמנט "עף" ממיקום אחד לאחר בין שני מצבים — כמו תמונת מוצר ש"גדלה" מ-thumbnail ל-full view
Slide Transitionמעבר החלקההעמוד הישן מחליק החוצה לכיוון אחד, החדש נכנס מהצד הנגדי — סגנון wizard/onboarding
Same-document transitionsמעברים בתוך מסמךמעברים בתוך SPA — הדף לא נטען מחדש, רק ה-DOM משתנה; מופעל עם document.startViewTransition()
Cross-document transitionsמעברים בין מסמכיםמעברים בין עמודים שונים (MPA) — כל לחיצה על קישור טוענת HTML חדש; מופעל עם @view-transition { navigation: auto }
Navigation APIממשק ניווטAPI חדש שמחליף חלק מ-history.pushState — משתלב בטבעיות עם View Transitions ב-SPAs
Page Transitionsמעברי עמודיםהמונח-על לכל מעבר בין שני מצבי UI; View Transitions הוא ה-implementation הנייטיבי שלהם ב-2025-2026
מתחיל 6 דקות חינם מושג

8.1 למה אתר מרגיש כמו "אתר" ואפליקציה כמו "אפליקציה"

יש טסט פשוט. פתחו את Instagram באייפון. פתחו את אינסטגרם בדפדפן ב-desktop (instagram.com). תחליקו בין תמונות, תיכנסו לפרופיל, תחזרו. שימו לב מה בדיוק מרגיש שונה. הפידים זהים. הצבעים זהים. האייקונים זהים. אבל משהו — משהו עמוק — עושה את ההבדל בין "זו אפליקציה" ל"זה אתר".

ההבדל הזה הוא מעברים. באפליקציה, כשאתם לוחצים על תמונת פרופיל, היא "גדלה" עד שהיא ממלאת את המסך. באתר, כשאתם לוחצים על קישור — המסך נהיה לבן לשבריר שנייה, ואז עמוד חדש "קופץ" במקום. זה hard page refresh, וזה הטל המרכזי שחושף אתר כאתר.

המעברים האלה — shared element transitions בלשון Material Design, hero animations בלשון iOS — היו עד 2023 בלעדיים לאפליקציות native. ב-web היית חייב לכתוב 200 שורות של JavaScript עם getBoundingClientRect(), requestAnimationFrame, ו-FLIP technique (First-Last-Invert-Play). זה היה מסובך, שביר, ולא-responsive. 90% מהאתרים פשוט ויתרו.

מה השתנה ב-2023-2026

ב-מרץ 2023, Chrome 111 הכניסו את View Transitions API — ה-native פתרון של הפלטפורמה. ב-ספטמבר 2024 הגיעה התמיכה ב-cross-document transitions (מעברים בין עמודים נפרדים, לא רק בתוך SPA). ב-2025-2026, Firefox ו-Safari מצטרפים. התוצאה: כל אתר, ב-3 שורות CSS, יכול להרגיש כמו אפליקציה.

זה לא מוגזם להגיד שזה אחד השינויים הכי גדולים בחוויית ה-web מאז responsive design. וכן — AI עדיין לא משתמש בזה כברירת-מחדל. זו בדיוק ההזדמנות שלכם.

התובנה הגדולה

המרחק בין "אתר" ל"אפליקציה" הוא היום 3 שורות של CSS, לא 200 שורות של JavaScript. View Transitions API הוא הטכנולוגיה הכי underrated של 2025-2026 — רוב המפתחים עדיין חושבים שצריך Framer Motion או GSAP בשביל זה. הם טועים. הפלטפורמה כבר פתרה את זה, חינם, native, performant.

למה זה משנה עסקית

עשו עכשיו 3 דקות

פתחו את live-transitions.pages.dev (או view-transitions.chrome.dev) בדפדפן Chrome. נווטו בין הדפים. שימו לב מה קורה למסך — הוא לא קופץ, הוא מתחלף בחלקות. עכשיו פתחו אותו ב-Firefox או Safari (אם אין לכם תמיכה, עדיין יעבוד — פשוט בלי האנימציה). ההבדל בין שתי החוויות הוא בדיוק מה שאתם תדעו לבנות בסוף הפרק הזה.

מתחיל 7 דקות חינם מושג

8.2 View Transitions API — מה זה, ואיך הוא שונה מ-@keyframes

הדרך הכי פשוטה להבין את View Transitions היא להשוות אותו ל-@keyframes הקלאסי שאתם כבר מכירים מפרק 7:

@keyframesView Transitions API
מניע אלמנט אחד ממצב A למצב Bמניע מעבר בין שני מצבי DOM שונים — יכול להיות בתוך עמוד או בין עמודים
האלמנט קיים בשני המצביםהאלמנט יכול להיעלם (DOM ישן) ולהופיע (DOM חדש) — הדפדפן מגשר
מופעל עם trigger (hover, click, class)מופעל עם document.startViewTransition() או ניווט רגיל
מתאים לאלמנטים יחידים: כפתור, כרטיס, נצרמתאים למעברים מבניים: ניווט, מיון, פילטרים, modals
לא יכול לעבור בין עמודיםעובד בין עמודים שונים (cross-document) ב-Chrome 126+

הקסם מאחורי הקלעים

כשאתם מפעילים View Transition, הדפדפן עושה משהו מורכב מאחורי הקלעים:

  1. צילום של ה-DOM הנוכחי (העמוד הישן) — מעין screenshot וירטואלי בזיכרון.
  2. ביצוע השינוי — החלפת HTML, ניווט לעמוד חדש, או עדכון DOM.
  3. צילום של ה-DOM החדש.
  4. יצירת 7 pseudo-elements שמכילים את שני הצילומים (ישן + חדש).
  5. הפעלת fade-out על הישן ו-fade-in על החדש, בברירת-מחדל — אפשר להחליף את זה ב-@keyframes משלכם.
  6. הסרת ה-pseudo-elements כשהמעבר מסתיים.

זה הסיבה שמרגישים כמו אפליקציה — הדפדפן מטפל באנימציה ב-compositor thread, ב-60fps, גם אם ה-DOM השתנה לחלוטין בין שני המצבים.

שלושה סוגי מעברים — בראייה גבוהה

  1. Cross-fade (ברירת-מחדל) — העמוד הישן דוהה לשקיפות, החדש מופיע. 3 שורות CSS, אפקט מיידי.
  2. Morph / Shared Element — אלמנט ספציפי (תמונה, כותרת) "עף" ממיקום ישן למיקום חדש. דורש view-transition-name ייחודי על האלמנט בשני המצבים.
  3. Slide — העמוד הישן מחליק החוצה, החדש נכנס מהצד. דורש @keyframes משלכם על ה-pseudo-elements.

נעבור על שלושתם במתכונים מלאים בסעיפים 8.6, 8.7, ו-8.8. אבל קודם — נבין את ה-building blocks.

עשו עכשיו 2 דקות

פתחו את DevTools ב-Chrome (F12). לכו ל-Animations panel (אם לא רואים — לחצו על 3 הנקודות → More tools → Animations). עכשיו חזרו לאתר מה-Do Now הקודם ונווטו בין העמודים. תראו בפאנל את ה-view transition animations נרשמות בזמן אמת. לחצו עליהן — אתם תראו את 7 ה-pseudo-elements שהדפדפן יצר. זה ה-proof שזה לא קסם — זו CSS רגיל מתחת.

בינוני 8 דקות חינם מעשי

8.3 document.startViewTransition() — נקודת הכניסה ב-JavaScript

ל-same-document transitions (SPA, React, Vue, Svelte) — זו השורה שמפעילה הכל:

document.startViewTransition(() => {
  // כאן אתם מעדכנים את ה-DOM.
  // הדפדפן יצלם "לפני", יריץ את הפונקציה, יצלם "אחרי", ויעביר ביניהם.
  updateTheDOM();
});

זהו. תנאי יחיד: הפונקציה שמועברת חייבת לעדכן את ה-DOM בצורה סינכרונית, או להחזיר Promise ש-resolve אחרי העדכון.

דוגמה מלאה — מיון רשימה עם fade

const sortBtn = document.querySelector('#sort-btn');
const list = document.querySelector('#product-list');

sortBtn.addEventListener('click', () => {
  // בדיקת תמיכה — חיוני!
  if (!document.startViewTransition) {
    sortList();  // fallback: מיון רגיל, בלי אנימציה
    return;
  }

  // הפעלת המעבר
  document.startViewTransition(() => sortList());
});

function sortList() {
  const items = [...list.children];
  items.sort((a, b) => +a.dataset.price - +b.dataset.price);
  items.forEach(item => list.appendChild(item));
}

התוצאה: כשלוחצים על "מיון לפי מחיר", הפריטים לא קופצים למיקומים החדשים — הם זוחלים בחלקות. 4 שורות של boilerplate (startViewTransition + בדיקת תמיכה) הוסיפו חוויית app.

תחזיר Promise אם העדכון async

document.startViewTransition(async () => {
  const newData = await fetch('/api/products').then(r => r.json());
  renderProducts(newData);
});

שימו לב: הדפדפן "יקפיא" את המצב הישן על המסך עד שה-Promise מסתיים. אם ה-fetch לוקח 3 שניות — הגולש רואה מסך קפוא 3 שניות. תמיד עטפו fetch-ים איטיים ב-Promise.race עם timeout של 200-300ms לכל היותר, או תשתמשו ב-skeleton screen מחוץ למעבר.

מה מחזיר הפונקציה

startViewTransition מחזיר אובייקט עם 3 Promises שימושיים:

const transition = document.startViewTransition(() => updateDOM());

transition.ready.then(() => {
  // ה-pseudo-elements נוצרו; אפשר להוסיף animations דינמית
});

transition.finished.then(() => {
  // המעבר הסתיים; זמן טוב לניקוי
});

transition.updateCallbackDone.then(() => {
  // ה-DOM update הסתיים (הפונקציה רצה), אבל האנימציה עדיין בתהליך
});

ב-95% מהמקרים לא תצטרכו את זה. אבל כשתרצו לסנכרן דברים (למשל להפעיל sound effect בדיוק בסוף המעבר) — transition.finished הוא החבר שלכם.

עשו עכשיו 5 דקות

פתחו StackBlitz (או CodePen). צרו HTML עם 5 div-ים ברשימה, וכפתור "shuffle". כתבו JS שעושה items.sort(() => Math.random() - 0.5) ומסדר מחדש את ה-DOM. ריצו — הפריטים יקפצו. עכשיו עטפו את הסידור ב-document.startViewTransition(() => ...). ריצו שוב — הם יזחלו בחלקות. זו הדרך הכי מהירה להרגיש את הקסם.

בינוני 10 דקות חינם מעשי

8.4 view-transition-name — איך "לסמן" אלמנט שמשתתף במעבר

ברירת-המחדל של View Transitions היא cross-fade גלובלי — כל העמוד דוהה, כל העמוד מופיע. זה נחמד, אבל לא מרשים. הקסם האמיתי מתחיל כשאלמנט ספציפי עובר בצורה שונה מהשאר — למשל תמונת מוצר שגדלה מ-thumbnail ל-full view, בזמן שכל השאר עושה cross-fade רגיל.

לשם כך צריך view-transition-name. זה CSS property שאומר לדפדפן "האלמנט הזה מקבל טיפול מיוחד — עקוב אחריו בנפרד".

ה-syntax הבסיסי

.product-card__image {
  view-transition-name: product-hero-image;
}

עכשיו, בכל מעבר, אם קיים אלמנט עם view-transition-name: product-hero-image ב-לפני וגם ב-אחרי — הדפדפן יתאים ביניהם וייצר morph animation.

הכלל הקריטי: ייחודיות

בכל רגע נתון, לכל view-transition-name חייב להיות בדיוק אלמנט אחד על העמוד. אם יש שניים — המעבר ייכשל בשקט, והאלמנטים יקפצו כמו בלי View Transitions. זה הטעות המס' 1 של מתחילים.

טעות נפוצה: view-transition-name זהה על 12 כרטיסים

מה קורה: מגדירים .card { view-transition-name: card } על class משותף. כל 12 הכרטיסים ברשימה מקבלים את אותו שם. המעבר נשבר — כל הכרטיסים "קופצים" במקום לזרום.

למה זה מפתה: נראה הגיוני — כולם כרטיסים, כולם מקבלים אותו style. ככה CSS עובד בכל מקום אחר.

מה לעשות במקום: או לתת שם ייחודי לכל כרטיס עם אינדקס: style="view-transition-name: card-{index}" (ב-React/Vue בקלות), או להשתמש ב-CSS fallback: .card:nth-child(1) { view-transition-name: card-1; } וכו'. החל מ-Chrome 125 יש גם view-transition-class שמאפשר לעצב קבוצות בלי להפר ייחודיות — אבל זה עדיין בזהירות.

מתכון: תיוג כרטיס מוצר שלם כ-"morph group"

אתם רוצים שכשהגולש ילחץ על כרטיס מוצר ברשימה, התמונה, הכותרת, והמחיר יעופו בחלקות למיקומים החדשים בעמוד הפריט. הנה ה-CSS:

/* בעמוד הרשימה */
.product-card[data-id="42"] .product-image {
  view-transition-name: product-42-image;
}
.product-card[data-id="42"] .product-title {
  view-transition-name: product-42-title;
}
.product-card[data-id="42"] .product-price {
  view-transition-name: product-42-price;
}

/* בעמוד הפריט */
.product-detail__hero-image {
  view-transition-name: product-42-image;
}
.product-detail__title {
  view-transition-name: product-42-title;
}
.product-detail__price {
  view-transition-name: product-42-price;
}

שימו לב: אותם 3 שמות בשני העמודים, אבל על סלקטורים שונים. הדפדפן מתאים ביניהם ובונה אנימציה של morph עבור כל אחד. התוצאה: חוויה זהה ל-iOS App Store.

יצירת שם דינמית ב-React/Vue

בפועל, אתם לא תכתבו CSS ידני לכל מוצר. תעבירו את השם כ-inline style:

// React
<img
  src={product.image}
  style={{ viewTransitionName: `product-${product.id}-image` }}
/>

// Vue
<img
  :src="product.image"
  :style="{ viewTransitionName: `product-${product.id}-image` }"
/>

זה הדפוס הסטנדרטי: שם מבוסס ID. אם יש לכם 100 מוצרים בעמוד, יהיו 100 view-transition-name שונים — וזה בסדר גמור, כי רק אלה שמופיעים בשני העמודים יעברו morph.

עשו עכשיו 4 דקות

פתחו אתר e-commerce שאתם אוהבים (Zalando, ASOS, KSP, או כל אחד). לחצו על כרטיס מוצר והסתכלו איך העמוד עובר. האם התמונה "עפה" או "קופצת"? האם הכותרת נשארת במקום או מתחלפת? אם אתם רואים morph — אתם יודעים שהאתר מיישם View Transitions (או FLIP ידני). אם הכל קופץ — האתר עדיין לא עושה את זה, וזה מה שאתם תבנו בעצמכם בסוף הפרק.

מתקדם 10 דקות חינם מעשי

8.5 ::view-transition pseudo-elements — 7 השכבות של המעבר

כש-View Transition מתחיל, הדפדפן בונה עץ של 7 pseudo-elements וירטואליים. הם לא נראים ב-DOM הרגיל, אבל אפשר לעצב אותם עם CSS. הכרה שלהם = שליטה מלאה במעבר.

Pseudo-elementמה זהמתי לעצב
::view-transitionה-root — השכבה שמכילה את הכללעיתים נדירות — רק לקביעת pointer-events או z-index גלובלי
::view-transition-group(root)קבוצת ברירת-המחדל — כל מה שאין לו שם ייחודיכשרוצים לשלוט ב-duration/easing של ה-cross-fade הכללי
::view-transition-group(name)הקבוצה של אלמנט מסומן עם view-transition-name: nameכשרוצים animation מותאם לאלמנט — לדוגמה תמונת hero
::view-transition-image-pair(name)המיכל שמכיל את שתי הגרסאות (old + new)ל-mix-blend-mode או positioning מיוחד
::view-transition-old(name)ה-snapshot של ה-DOM הישןלשנות את ה-fade-out: duration, easing, transform
::view-transition-new(name)ה-snapshot של ה-DOM החדשלשנות את ה-fade-in: duration, easing, transform
::view-transition-rootalias ל-::view-transition בחלק מהמפרטיםבד"כ לא — השתמשו ב-::view-transition

דוגמה: שליטה ב-duration של ה-cross-fade הכללי

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.4s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}

שורה אחת — ה-fade-out וה-fade-in עכשיו לוקחים 400ms (במקום 250ms ברירת-המחדל) עם easing של "ease-out expo" (קלאסי של Linear, Vercel, Framer).

דוגמה: מעבר custom על כרטיס hero

/* החלף את ה-fade הסטנדרטי ב-scale-fade לתמונת ה-hero */
::view-transition-old(hero-image) {
  animation: scale-out 0.3s ease-in forwards;
}

::view-transition-new(hero-image) {
  animation: scale-in 0.3s ease-out backwards;
}

@keyframes scale-out {
  to { opacity: 0; transform: scale(1.2); }
}

@keyframes scale-in {
  from { opacity: 0; transform: scale(0.8); }
}

עכשיו תמונת ה-hero לא סתם דוהה — היא "מתקרבת ומתרחקת" תוך כדי fade. זה הדפוס של Apple.com וגם של Dribbble.

עשו עכשיו 3 דקות

פתחו את אתר הדמו מה-Do Now הראשון. ב-DevTools, לכו ל-Elements ופתחו את ה-root (html). בזמן שאתם לוחצים על קישור, תסתכלו מהר על ה-DOM — תראו לרגע עץ של ::view-transition עם ילדים (::view-transition-group, ::view-transition-image-pair...). זה ה-"מאחורי הקלעים". אחרי כמה מאות מילישניות הוא נעלם.

מתחיל 8 דקות חינם מעשי

8.6 מתכון #1: Cross-fade — ברירת-מחדל ב-3 שורות

Cross-fade הוא המתכון הכי פשוט, והכי מומלץ כ-baseline. כמעט כל אתר יכול לקבל אותו בחינם — והוא כבר משנה 60% מהתחושה.

ל-MPA / Astro / static sites — שורה אחת

@view-transition {
  navigation: auto;
}

זהו. שימו את השורה הזו ב-CSS הגלובלי של האתר. כל ניווט בין עמודים יהיה cross-fade. עובד ב-Chrome 126+ ו-Edge 126+.

ל-SPA / React / Vue — wrapping של ניווט

// ב-App.jsx או ב-router wrapper
function navigate(url) {
  if (!document.startViewTransition) {
    window.location.href = url;  // fallback
    return;
  }
  document.startViewTransition(() => {
    // ה-router שלכם מעדכן את ה-DOM
    router.push(url);
  });
}

התאמה עדינה של ה-cross-fade

/* השתמשו בעיטור שקוף + duration נוח */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.25s;
  animation-timing-function: ease-out;
}

/* אל תרצו overlap? הריצו ברצף במקום במקביל */
::view-transition-image-pair(root) {
  isolation: auto; /* כברירת-מחדל יש blend; isolation: auto מחזיר לרגיל */
}

הוספת slide דק ב-RTL (מאוד ישראלי)

::view-transition-old(root) {
  animation: slide-out-rtl 0.3s ease-in forwards;
}
::view-transition-new(root) {
  animation: slide-in-rtl 0.3s ease-out backwards;
}

@keyframes slide-out-rtl {
  to { opacity: 0; transform: translateX(20px); }
}
@keyframes slide-in-rtl {
  from { opacity: 0; transform: translateX(-20px); }
}

שימו לב ל-translateX חיובי (20px ימינה) לעמוד הישן ו-שלילי (-20px משמאל) לעמוד החדש — בעברית RTL זו ההתקדמות הטבעית. אם אתם עובדים ב-LTR — החליפו את הסימנים.

טעות נפוצה: להוסיף transition על html/body

מה קורה: מפתחים מנסים "לעזור" עם html { transition: opacity 0.3s }. התוצאה: ה-transition הרגיל מתנגש עם View Transitions, והמעבר נשבר.

למה זה מפתה: כי transition מוכר, ו-View Transitions חדש ומפחיד.

מה לעשות במקום: לסמוך על View Transitions. אל תוסיפו CSS transitions על html/body. כל ה-animation נעשית ב-pseudo-elements. אם רוצים שליטה — השתמשו ב-::view-transition-old/new, לא ב-transition רגיל.

עשו עכשיו 5 דקות

פתחו את האתר האישי שלכם (הגנרי, מפרק 1), או כל אתר ב-StackBlitz. הוסיפו ל-CSS הגלובלי: @view-transition { navigation: auto; }. רעננו ב-Chrome. נווטו בין עמודים (אם זה static) או השתמשו ב-HTML hyperlinks רגילים. שימו לב לחוויה — מסך לבן נעלם, הכל הופך חלק. 3 שורות, חוויה של אפליקציה.

מתקדם 15 דקות חינם מעשי

8.7 מתכון #2: Morph / Shared Element — כרטיס שעובר לעמוד מלא

זה המתכון שבאמת עושה "וואו". הגולש לוחץ על כרטיס מוצר ברשימה — התמונה "גדלה" וזזה למיקום החדש בעמוד הפריט, הכותרת "זוחלת" למקום, המחיר "מתנגן" לגודל חדש. זו אפליקציה — לא אתר.

זה בדיוק הדפוס שהופך את iOS App Store ל-iOS App Store. ועכשיו הוא שורה של CSS.

המתכון המלא — כרטיס list → detail view

נניח שיש לכם רשימת מוצרים ב-/products ועמוד פרטי מוצר ב-/products/42. צעד 1 — תיוג הכרטיס:

<!-- /products -->
<a href="/products/42" class="product-card">
  <img
    src="/images/42.jpg"
    class="product-card__image"
    style="view-transition-name: product-42-image;"
  />
  <h3
    class="product-card__title"
    style="view-transition-name: product-42-title;"
  >
    אוזניות Sony WH-1000XM5
  </h3>
  <span
    class="product-card__price"
    style="view-transition-name: product-42-price;"
  >
    ₪1,499
  </span>
</a>

צעד 2 — תיוג אותם שמות בעמוד הפרטים:

<!-- /products/42 -->
<main class="product-detail">
  <img
    src="/images/42-large.jpg"
    class="product-detail__hero"
    style="view-transition-name: product-42-image;"
  />
  <h1
    class="product-detail__title"
    style="view-transition-name: product-42-title;"
  >
    אוזניות Sony WH-1000XM5 Noise Cancelling
  </h1>
  <div
    class="product-detail__price"
    style="view-transition-name: product-42-price;"
  >
    ₪1,499
  </div>
</main>

צעד 3 — הפעלת cross-document transitions (אם זה MPA):

@view-transition {
  navigation: auto;
}

/* Duration קצת יותר ארוך ל-morph, כדי שיראו את התנועה */
::view-transition-group(product-42-image),
::view-transition-group(product-42-title),
::view-transition-group(product-42-price) {
  animation-duration: 0.4s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}

זהו. 3 תגים, 3 שמות, 6 שורות CSS. התוצאה: תמונת המוצר "עפה" ממיקום הכרטיס למיקום ה-hero, הכותרת "זוחלת" לגודל החדש, המחיר "מתנגן". חוויית App Store, ב-CSS בלבד.

הפקת שמות דינמית — ב-React

ברור שלא תכתבו ידנית view-transition-name: product-42-image. בפועל תגנרו את זה:

// ProductCard.jsx
export function ProductCard({ product }) {
  const nameBase = `product-${product.id}`;
  return (
    <Link href={`/products/${product.id}`}>
      <img
        src={product.image}
        style={{ viewTransitionName: `${nameBase}-image` }}
      />
      <h3 style={{ viewTransitionName: `${nameBase}-title` }}>
        {product.title}
      </h3>
      <span style={{ viewTransitionName: `${nameBase}-price` }}>
        ₪{product.price}
      </span>
    </Link>
  );
}

טיפ: morph גם על ניווט מערבי (back button)

כשהגולש לוחץ Back, הדפדפן גם מפעיל View Transition — אבל הפוך (מעמוד הפרטים חזרה לרשימה). אם השמות זהים בשני העמודים — ה-morph עובד בשני הכיוונים אוטומטית. זו המתנה הכי גדולה של ה-API.

טעות נפוצה: morph על 20 כרטיסים במקביל

מה קורה: מגדירים view-transition-name על כל 20 הכרטיסים ברשימה. כשהגולש לוחץ על כרטיס מס' 7, כל ה-20 מקבלים morph — המסך הופך לכאוס של תמונות שזזות.

למה זה מפתה: נראה עקבי — כולם כרטיסים, כולם אותו דין.

מה לעשות במקום: להגדיר view-transition-name רק על הכרטיס ה-נלחץ, דינמית. ב-React אפשר להעביר state שמזהה את ה-id הנלחץ, ולהחיל את השם רק עליו לפני ה-navigation. או להשתמש ב-:has(): .card:has(a:active) { view-transition-name: active-card; } (סוגי browser support בהתאם).

עשו עכשיו 5 דקות

פתחו את chrome developer docs ל-View Transitions ולחצו על הלינק לדמו של "Shared Axis Transitions". שימו לב מה קורה בין העמודים — תמונת ה-hero של כל פוסט עפה חלק למקומה החדש. זה בדיוק מה שתבנו בתרגיל 2. שמרו את ה-URL.

בינוני 8 דקות חינם מעשי

8.8 מתכון #3: Slide — מעבר אופקי כמו wizard

Slide transition מתאים ל-wizard flows (רישום ב-3 שלבים), ל-carousel-like navigation, ול-onboarding screens. הוא משדר "רצף לינארי" — "עברנו לעמוד הבא בתהליך".

המתכון — ב-RTL (עברית)

/* כללי: Slide בכיוון "קדימה" — עמוד ישן יוצא משמאל, חדש נכנס מימין */
::view-transition-old(root) {
  animation: slide-out-ltr 0.35s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
::view-transition-new(root) {
  animation: slide-in-rtl 0.35s cubic-bezier(0.4, 0, 0.2, 1) backwards;
}

@keyframes slide-out-ltr {
  to { transform: translateX(-100%); opacity: 0.5; }
}
@keyframes slide-in-rtl {
  from { transform: translateX(100%); opacity: 0.5; }
}

Slide דו-כיווני — back button בכיוון הפוך

הבעיה: כשלוחצים Next, רוצים slide ימינה. כשלוחצים Back, רוצים slide שמאלה. אבל הדפדפן לא יודע את כיוון הניווט — הוא רק יודע "המעבר החל".

הפתרון: שימו טיימסטמפ או step number ב-URL או ב-sessionStorage. לפני ה-navigation, הוסיפו class ל-<html>:

// לפני ה-navigation
const direction = newStep > currentStep ? 'forward' : 'backward';
document.documentElement.dataset.navDirection = direction;

document.startViewTransition(() => {
  router.push(newUrl);
});
/* CSS: שני מצבים */
html[data-nav-direction="forward"] ::view-transition-old(root) {
  animation: slide-out-ltr 0.35s forwards;
}
html[data-nav-direction="forward"] ::view-transition-new(root) {
  animation: slide-in-rtl 0.35s backwards;
}

html[data-nav-direction="backward"] ::view-transition-old(root) {
  animation: slide-out-rtl 0.35s forwards;
}
html[data-nav-direction="backward"] ::view-transition-new(root) {
  animation: slide-in-ltr 0.35s backwards;
}

עכשיו ה-wizard שלכם מרגיש כמו app. Next מחליק קדימה, Back מחליק אחורה, והגולש יודע בדיוק "איפה הוא" בתהליך.

עשו עכשיו 3 דקות

פתחו אפליקציית onboarding באייפון (כל app חדש שהתקנתם). שימו לב לכיוון ה-slides: לאן זזים, כמה זמן, איזה easing (האם מרגיש "ספרינג" או "קבוע"?). זה בדיוק ה-reference שאתם תנסו לשחזר ב-web עם המתכון למעלה.

בינוני 8 דקות חינם מושג

8.9 Same-document מול Cross-document — ההבדל הקריטי

זה ההבדל המושגי החשוב ביותר בפרק, ולצערנו גם זה שמבלבל הכי הרבה אנשים. בואו נעשה סדר.

Same-document (SPA)Cross-document (MPA)
מה זהניווט בתוך אותו עמוד — ה-URL משתנה אבל הדף לא נטען מחדשניווט בין עמודים שונים — דף HTML חדש נטען מהשרת
דוגמאותReact app, Vue app, Svelte app, Angular app, Next.js עם client routing, Gmail, TwitterAstro (ברירת-מחדל), WordPress, static HTML sites, Next.js App Router עם server-side navigation
איך מפעיליםdocument.startViewTransition(() => updateDOM())@view-transition { navigation: auto } ב-CSS
תמיכה בדפדפנים (2026-04)Chrome/Edge 111+, Safari 18, Firefox מגיעChrome/Edge 126+, Safari 18.2, Firefox בתכנון
Fallback אוטומטיאם אין תמיכה — הפונקציה פשוט רצה בלי אנימציהאם אין תמיכה — ניווט רגיל עם page flash

איך יודעים באיזה אני?

שאלו את עצמכם: כשאני לוחץ קישור באתר שלי, האם הכתובת בכתובית משתנה אחרי שהרשת טוענת דבר חדש (MPA), או לפני, ואז JavaScript מעדכן את התוכן (SPA)?

יתרונות וחסרונות של כל גישה

SPA (same-document):

MPA (cross-document):

מסגרת החלטה: Same-document מול Cross-document
מצבתוצאה
יש לכם Next.js App Router, Remix, Astro, או WordPress← Cross-document. השתמשו ב-@view-transition { navigation: auto }. שורה אחת, סוף הדרך.
יש לכם React SPA, Vue SPA, Svelte (לא SvelteKit), או vanilla JS עם history.pushState← Same-document. עטפו את ה-navigation ב-document.startViewTransition().
יש לכם Next.js Pages Router או Gatsby (hybrid)← Same-document לרוב. Next.js 14+ מציע unstable_ViewTransition component שעוטף את זה אוטומטית.
בוני אתר סטטי עם HTML+CSS בלבד (בלי framework)← Cross-document. שורה אחת ב-CSS ויש לכם מעבר.
לא בטוחים?← פתחו DevTools → Network. לחצו על קישור פנימי. אם יש request חדש של HTML document — MPA. אם לא — SPA.
בינוני 10 דקות חינם מעשי

8.10 Cross-document ל-MPA — Astro, static sites, ו-@view-transition

Cross-document transitions הן ההפצצה של 2024-2026. אתר HTML סטטי של שנת 1999 יכול לקבל "תחושת אפליקציה" עם שורה אחת של CSS. אין צורך ב-framework, אין צורך ב-JavaScript, אין צורך ב-build step.

The simplest possible setup

יצרו שני קבצים:

<!-- /index.html -->
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
  <link rel="stylesheet" href="/styles.css">
</head>
<body>
  <h1>עמוד ראשי</h1>
  <a href="/about.html">לאודות →</a>
</body>
</html>
<!-- /about.html -->
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
  <link rel="stylesheet" href="/styles.css">
</head>
<body>
  <h1>אודות</h1>
  <a href="/index.html">← חזרה</a>
</body>
</html>
/* /styles.css */
@view-transition {
  navigation: auto;
}

פתחו את index.html ב-Chrome. לחצו "לאודות". המסך לא קפץ — הוא התחלף בחלקות. 3 קבצים, 0 JavaScript, חווית app.

דרישות הבסיס — מה חייב להיות

  1. קובץ CSS גלובלי עם @view-transition { navigation: auto }. חייב להיות טעון בשני העמודים.
  2. ניווט ב-<a> tag רגיל — לא ב-window.location, לא ב-form.submit(), לא ב-fetch. הדפדפן מפעיל את המעבר רק על ניווט סמנטי.
  3. same-origin navigation — מעבר לדומיין אחר לא יפעיל View Transition (זה מגבלת אבטחה).
  4. HTML דומה מספיק — אם מבנה ה-DOM שונה דרמטית, ה-cross-fade עדיין יעבוד, אבל morph לא.

Opt-out של מעברים ספציפיים

@view-transition {
  navigation: auto;
}

/* אל תפעיל מעברים אם ה-URL מכיל '/admin/' */
@media (prefers-reduced-motion: no-preference) {
  /* ברוב המקרים לא צריך - אבל אפשר לבטל דרך JS: */
}

לבטל מעבר ספציפי דרך JS:

document.addEventListener('pageswap', (event) => {
  if (event.viewTransition && shouldSkip(event.activation.to.url)) {
    event.viewTransition.skipTransition();
  }
});

Astro — מובנה לחלוטין

Astro 4+ מספק View Transitions integration מובנה:

---
// src/layouts/Layout.astro
import { ViewTransitions } from 'astro:transitions';
---

<html lang="he" dir="rtl">
  <head>
    <ViewTransitions />
  </head>
  <body>
    <slot />
  </body>
</html>

שורה אחת ב-<head>, ו-Astro דואג לכל השאר: cross-document transitions, named transitions, polyfill לדפדפנים ישנים, ו-persistent state בין עמודים. זה אחד הפיצ'רים שעושים Astro אטרקטיבי ב-2026.

בינוני 10 דקות חינם כלי

8.11 Frameworks — Astro, Next.js App Router, React Router v7

האמת: רוב האתרים המקצועיים לא נכתבים ב-vanilla HTML. בואו נראה איך View Transitions משתלב בכל framework מרכזי באפריל 2026.

Astro 4.5+

הכי פשוט. מובנה, ללא setup נוסף:

---
import { ViewTransitions } from 'astro:transitions';
---
<html><head><ViewTransitions /></head>...</html>

אפשר גם להוסיף transition:name="unique-name" directive על כל אלמנט, ו-Astro ממיר אוטומטית ל-view-transition-name עם polyfill לדפדפנים שעוד אין להם תמיכה native.

Next.js App Router (15+)

Next.js 15 הכניסו unstable_ViewTransition component (צפוי להיות stable ב-Next 16):

// app/layout.tsx
import { unstable_ViewTransition as ViewTransition } from 'react';

export default function Layout({ children }) {
  return (
    <html lang="he" dir="rtl">
      <body>
        <ViewTransition>
          {children}
        </ViewTransition>
      </body>
    </html>
  );
}

לתיוג אלמנטים ספציפיים:

<ViewTransition name={`product-${product.id}-image`}>
  <img src={product.image} />
</ViewTransition>

שימו לב ש-Next.js מפעיל את זה על route transitions אוטומטית — אין צורך לעטוף router.push ידנית.

React Router v7

React Router v7 (יצא 2024) כולל ViewTransition component מובנה:

import { Link } from 'react-router';

<Link to="/products/42" viewTransition>
  מוצר 42
</Link>

ה-viewTransition prop על Link עוטף אוטומטית את ה-navigation ב-document.startViewTransition. אין צורך ביותר.

SvelteKit

SvelteKit עדיין לא מציע API ייעודי (נכון לאפריל 2026), אבל שילוב ידני פשוט בקובץ +layout.svelte:

<script>
  import { onNavigate } from '$app/navigation';

  onNavigate((navigation) => {
    if (!document.startViewTransition) return;

    return new Promise((resolve) => {
      document.startViewTransition(async () => {
        resolve();
        await navigation.complete;
      });
    });
  });
</script>

טבלת השוואה

FrameworkSetupNamed transitionsPolyfillProduction-ready
Astro 4.5+1 שורה: <ViewTransitions />transition:nameמובנהכן, מ-2024
Next.js 15 App Router1 component: <unstable_ViewTransition>name propאין (stable browser only)Experimental; צפוי stable ב-Next 16
React Router v7prop: <Link viewTransition>ידני עם styleאיןכן, מ-2024
SvelteKitwrapper ידני ב-onNavigateידניאיןעובד, דורש boilerplate
Vue Router 4+wrapper ב-beforeEachידניאיןעובד, דורש boilerplate
vanilla HTML1 שורה CSS: @view-transitionידניאיןכן, 2024+ Chrome
עשו עכשיו 3 דקות

חשבו על הפרויקט הנוכחי שלכם. באיזה framework הוא? רשמו בפינת המסך: (א) Framework = ____, (ב) Setup line = ____. אם אתם לא בטוחים — חפשו ב-package.json (ניתן לפתוח ישירות ב-IDE) והשוו לטבלה. בתרגיל 3 תפעילו View Transitions דווקא בפרויקט הזה.

בינוני 6 דקות חינם מושג

8.12 Browser support — אפריל 2026, ו-fallback אלגנטי

מצב התמיכה עבר שינויים דרמטיים בין 2023 ל-2026. הנה ה-snapshot נכון לאפריל 2026 (freshness-sensitive — בדקו את caniuse.com לפני deployment):

דפדפןSame-documentCross-documentהערות
Chrome / Chromium111+ (מרץ 2023)126+ (יוני 2024)תמיכה מלאה, יציבה
Edge111+126+זהה ל-Chrome
Safari18+ (ספטמבר 2024)18.2+ (דצמבר 2024)תמיכה מלאה ב-iOS 18 ו-macOS Sonoma
Firefoxבתכנון (Nightly 2026)בתכנוןנמצא ב-"in development"; צפוי ב-2026-2027
Samsung Internet25+ (יוני 2024)טרםעוקב אחרי Chromium

שימו לב: נתוני התמיכה משתנים במהירות. תמיד בדקו ב-caniuse.com/view-transitions לפני שאתם שולחים לפרודקשן.

Progressive enhancement — הפילוסופיה

View Transitions תוכנן מראש כ-progressive enhancement. זה אומר: הוא לא שובר שום דבר. אם הדפדפן לא תומך — הניווט פשוט קורה בלי אנימציה. אין לכם מה לדאוג ל-Firefox משנת 2020 שנכנס לאתר שלכם — הוא יראה את האתר כרגיל, בלי הבונוס.

Feature detection

ל-same-document:

if (document.startViewTransition) {
  // יש תמיכה
  document.startViewTransition(() => updateDOM());
} else {
  // fallback
  updateDOM();
}

ל-cross-document אין feature detection דרך JS — אבל CSS יודע להתעלם ממה שהוא לא מכיר:

/* Firefox ישן פשוט יתעלם. אין שבירה. */
@view-transition {
  navigation: auto;
}

Fallback Checklist

  1. האתר שלכם חייב לעבוד 100% בלי View Transitions. בדקו ב-Firefox או ב-Chrome incognito עם disable JavaScript.
  2. הוסיפו @supports אם אתם מחילים רק styles מיוחדים: @supports (view-transition-name: a) { ... }.
  3. אל תשלבו state קריטי ב-startViewTransition. העדכון ל-DOM חייב לעבוד גם בלי ה-wrapping.
  4. בדקו על מכשיר אמיתי (לא רק DevTools emulation) — iOS Safari 17 ו-Firefox Android עלולים להתנהג אחרת.
  5. הריצו Lighthouse — ה-accessibility ו-performance score לא אמורים לרדת.
  6. Core Web Vitals: ודאו ש-LCP לא נפגע. מעברים כבדים (morph של תמונות 5MB) יכולים לדחוף LCP מעל 2.5 שניות.
עשו עכשיו 4 דקות

פתחו את caniuse.com/view-transitions. רשמו את ה-"Global" percentage (כמה אחוז מהמשתמשים בעולם יש להם תמיכה). עכשיו שימו לב לפלח של Firefox ו-Safari ישן. עבור אתר ישראלי, 95%+ מהגולשים כבר משתמשים ב-Chrome / Safari מודרני / Edge. זה אומר שהפיצ'ר הזה כבר production-ready לרוב הפרויקטים שלכם — עם fallback נקי ל-5% הנותרים.

בינוני 8 דקות חינם אסטרטגיה

8.13 Performance & UX rules — 1-3 אלמנטים, 300ms, reduced-motion

View Transitions הוא עוצמתי, ולכן קל לנצל אותו לרעה. הכלל הזהב: מעבר חלק מרגיש טבעי; מעבר מתוחכם מרגיש מוגזם. הנה 5 כללים ש-99% מהמפתחים מפרים — ואתם לא תפרו.

כלל 1: 1-3 אלמנטים מסומנים, לא יותר

אם אתם מתייגים 20 אלמנטים עם view-transition-name, המעבר יהפוך לכאוס של תנועה. העין של הגולש לא יכולה לעקוב אחרי 20 דברים שזזים במקביל. המלצה: 1 אלמנט ראשי (תמונת hero), 1-2 משניים (כותרת, מחיר) — וזהו. כל השאר — cross-fade כברירת-מחדל.

כלל 2: duration 200-400ms, לא יותר

מעבר של 500ms+ מרגיש "איטי" לגולש. מעבר של פחות מ-150ms מרגיש "מהיר מדי" — הגולש לא מרגיש את האנימציה. ה-sweet spot: 250ms ל-cross-fade, 300-400ms ל-morph.

כלל 3: prefers-reduced-motion — חובה, לא אופציונלי

יש משתמשים שהתנועה גורמת להם ל-motion sickness. יש משתמשים שיצרו setting "reduced motion" ב-OS. לכבד אותם זה לא bonus — זו דרישת נגישות:

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

זהו. 6 שורות CSS. משתמשים עם reduced-motion יקבלו ניווט מיידי בלי אנימציה — בדיוק כמו שהם רוצים.

כלל 4: אל תחסמו את ה-UI

אם המעבר לוקח 400ms, הגולש לא יכול לבטל את הניווט או ללחוץ Back במהלכו. זה OK ל-300ms, מתחיל להיות בעייתי ב-500ms+. אל תעשו מעברים ארוכים על interactions שהגולש עושה הרבה (חיפוש, פילטר, מיון).

כלל 5: test על mobile אמיתי

Safari iOS ו-Chrome Android יכולים להתנהג שונה מ-desktop. morph של תמונה גדולה על iPhone 12 עלול לקפוץ. בדקו תמיד על 2-3 מכשירים פיזיים לפני שליחה ל-production.

מסגרת החלטה: כמה אלמנטים לתייג
סוג המעברמספר אלמנטים מתויגיםדוגמה
Cross-fade בלבד0מעבר בין עמודי About → Services
Hero spotlight1רק תמונת hero של בלוג מעברה לעמוד הכתבה
Product morph2-3תמונה + כותרת + מחיר של מוצר (e-commerce classic)
Dashboard transition3-5sidebar active link + header + main content area
Gallery spotlight1תמונת גלריה → lightbox. לעולם לא 2+.
>5 אלמנטים← STOPאם אתם חושבים "גם וגם וגם", אתם טועים. קצצו.
עשו עכשיו 3 דקות

פתחו את Settings במחשב שלכם. ב-macOS: System Preferences → Accessibility → Display → "Reduce motion". ב-Windows: Settings → Accessibility → Visual effects → Animation effects = Off. עכשיו חזרו לאתר הדמו (מה-Do Now הראשון). האם האנימציות עדיין קורות? אם כן — האתר לא מכבד את ההעדפה, וזה bug. אם הן נעלמו — האתר בנוי נכון.

בינוני 8 דקות חינם אסטרטגיה

8.14 איך לבקש מ-AI View Transitions — 3 פרומפטים מדויקים

אם תבקשו מ-AI "add smooth page transitions", תקבלו cross-fade גנרי — או גרוע מזה, פתרון של 200 שורות JavaScript עם Framer Motion. הסוד הוא להיות ספציפיים. הנה 3 templates שעובדים:

Prompt #1 — Cross-fade עם fallback

Add a cross-fade View Transitions API to this site.

Requirements:
- Use @view-transition { navigation: auto } for cross-document support (MPA/Astro)
- Set transition duration to 250ms with ease-out timing
- Include a @media (prefers-reduced-motion: reduce) fallback that disables
  all view-transition animations
- Do NOT add any CSS transitions on html or body elements
- Do NOT add JavaScript — CSS-only solution
- Ensure the site still works perfectly in browsers without support (Firefox, Safari 17)

Show me only the CSS I need to add, and the file where to put it.

Prompt #2 — Morph transition בין כרטיס לעמוד פרטי

Add a morph View Transition between the product list page and the product
detail page for product id={productId}.

Elements to morph (use unique view-transition-name for each):
- Product image: view-transition-name: product-{id}-image
- Product title: view-transition-name: product-{id}-title
- Product price: view-transition-name: product-{id}-price

Requirements:
- Add the view-transition-name via inline style (for React/Vue), so it can be
  generated from the product id dynamically
- Match element names in BOTH the list card AND the detail page
- Use cubic-bezier(0.16, 1, 0.3, 1) for the group animation (ease-out expo)
- Set animation-duration to 400ms for morph elements, 250ms for everything else
- Include prefers-reduced-motion fallback that disables morph but keeps the navigation working
- Do NOT add view-transition-name on a shared class (.card) — it must be per-item

Frameworks: I'm using {React|Vue|Astro|vanilla}. Use appropriate syntax.

Prompt #3 — Slide transition בסגנון wizard (RTL)

Add a slide View Transition for a 3-step wizard in Hebrew (RTL direction).

Behavior:
- Next button: old page slides OUT to the left, new page slides IN from the right
- Back button: old page slides OUT to the right, new page slides IN from the left
- Track navigation direction in a data-nav-direction attribute on <html> element
- Duration: 350ms with cubic-bezier(0.4, 0, 0.2, 1)
- Include prefers-reduced-motion fallback
- Use translateX and opacity 0.5 at the midpoint for a polished effect

Framework: {Next.js App Router | Astro | vanilla JS}

Return: (1) the CSS for both directions, (2) the JS that sets the
data-nav-direction before calling startViewTransition.

מה הופך את הפרומפטים האלה לעובדים

עשו עכשיו 4 דקות

העתיקו את Prompt #1 לכלי AI שאתם משתמשים בו (Claude, ChatGPT, Cursor, v0). הריצו. קבלו את ה-CSS. הוסיפו אותו לאתר שלכם בקובץ CSS גלובלי. רעננו את הדפדפן ב-Chrome. נווטו בין שני עמודים באתר. האם יש cross-fade? אם כן — הצלחתם. אם לא — בדקו שיש לכם 2 עמודים שונים (.html נפרדים), והקובץ CSS טעון בשניהם.

מתקדם 8 דקות חינם ניתוח

8.15 Gotchas — 5 בעיות שכולם נתקלים בהן

Gotcha 1: display: none שובר morph

אלמנט עם display: none לא מצולם בזמן View Transition. אם התמונה שלכם מוסתרת ב-display: none בעמוד אחד ו-display: block בשני, ה-morph ייכשל.

הפתרון: השתמשו ב-visibility: hidden + opacity: 0, או ב-conditional rendering ב-React/Vue שמסיר את האלמנט לגמרי (לא רק מסתיר).

Gotcha 2: שם view-transition-name זהה בשני אלמנטים בו-זמנית

כבר דיברנו על זה — הנה עוד scenario. יש לכם sticky header עם לוגו שמקבל view-transition-name: logo. הלוגו מופיע גם ב-footer. בזמן מעבר — שני אלמנטים עם אותו שם. View Transition נשבר.

הפתרון: שמות ייחודיים — logo-header, logo-footer. לעולם לא לחזור על שם.

Gotcha 3: Mobile Safari מגמגם על morph של תמונות גדולות

iPhone 12 / 13 עם תמונה של 4MB תגרום ל-View Transition לגמגם ב-5-10 frames. הסיבה: הצילום עצמו לוקח זמן על mobile.

הפתרון: (א) תמונות מאופטמות — WebP/AVIF תחת 200KB. (ב) image-rendering: optimizeSpeed על תמונות במעבר. (ג) test על מכשיר אמיתי, לא רק DevTools.

Gotcha 4: מעברים לא עובדים עם window.location.href

אם ב-JS שלכם אתם משתמשים ב-window.location.href = '/page2' לניווט, Cross-document View Transitions לא יפעלו. הדפדפן מפעיל אותם רק על ניווט סמנטי (<a> tag click, form submit, history.back).

הפתרון: השתמשו ב-<a href="..."> במקום window.location.href. אם חייבים JS, עטפו ב-document.startViewTransition ידנית.

Gotcha 5: iframe-ים לא תומכים

אם ה-site שלכם משובץ ב-iframe (widget, chatbot), View Transitions בתוך ה-iframe עלולים לא לעבוד עקב הגבלות cross-origin.

הפתרון: חיו עם זה. iframe הוא sandbox, ומעברים בתוכו הם edge-case. אם חיוני — scroll ב-host document במקום ניווט ב-iframe.

טעות נפוצה: לחסוך על fallback לחשוב "רוב הגולשים ב-Chrome"

מה קורה: המפתח אומר "95% ב-Chrome, לא כדאי להוסיף fallback". שולח לפרוד. יום אחד, בנאדם עם Firefox נכנס. החוויה שבורה — לחיצה על קישור לא מראה כלום למשך 300ms, ואז עמוד קופץ. הוא חושב "האתר הזה דפוק" ועוזב.

למה זה מפתה: האחוזים באמת קטנים, וה-fallback דורש 6 שורות של CSS.

מה לעשות במקום: fallback אלגנטי הוא תמיד חובה. זה לא 5% מהגולשים — זה 5% מהרושם הראשון. הוסיפו @media (prefers-reduced-motion: reduce) + בדיקת תמיכה ב-JS. Firefox Desktop 5%. Safari 17 (עדיין בשימוש) 3%. WebView on old Android 4%. זה 12% שעלול להתרשם רע. 6 שורות CSS זה מחיר זול להימנע מזה.

עשו עכשיו 3 דקות

פתחו את האתר האישי שלכם ב-Firefox (אם אין לכם — התקינו עכשיו, לוקח דקה). לחצו בין דפים. רשמו מה אתם רואים — האם הניווט עובד חלק, או שיש page flash? האם יש שגיאות ב-console? אם הכל עובד (רק בלי האנימציה של Chrome) — ה-progressive enhancement שלכם עובד. אם יש שבירה — זה ה-bug מס' 1 שצריך לתקן לפני שמיישמים View Transitions.

תרגיל 1: Cross-fade Setup — Site-wide ב-10 דקות 20 דקות
  1. פתחו StackBlitz חדש — template "Static" (או vanilla HTML/CSS).
  2. צרו 3 קבצי HTML: index.html, about.html, contact.html. בכל אחד שימו כותרת, פסקה, ו-3 קישורים לשני העמודים האחרים.
  3. צרו קובץ styles.css גלובלי. טענו אותו בכל 3 העמודים.
  4. הוסיפו ל-styles.css: @view-transition { navigation: auto; }.
  5. הוסיפו: ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.25s; animation-timing-function: ease-out; }.
  6. הוסיפו @media (prefers-reduced-motion: reduce) שמבטל את האנימציות.
  7. בדקו ב-Chrome — נווטו בין 3 העמודים. תראו cross-fade.
  8. פתחו DevTools → Animations panel. הפעילו מעבר. צלמו screenshot של ה-view-transition animations ברשימה.
  9. הפעילו "Reduce motion" במערכת. נווטו שוב — האנימציות צריכות להיעלם.
  10. פתחו את אותו האתר ב-Firefox — ודאו שהניווט עובד חלק, בלי שבירה.

מה צריך להיות בסוף: פרויקט StackBlitz עם 3 עמודים + cross-fade transitions + reduced-motion fallback + 3 screenshots (Chrome עם animations, Chrome עם reduced-motion, Firefox ללא animations אבל עם ניווט תקין).

תרגיל 2: Morph Transition על כרטיס מוצר 30 דקות
  1. בפרויקט StackBlitz חדש, צרו HTML list עם 4 כרטיסי מוצר ב-/products.html. כל כרטיס: תמונה (unsplash.com), כותרת, מחיר, קישור ל-/product-{id}.html.
  2. צרו 4 עמודי פרטים: product-1.html עד product-4.html. בכל אחד: אותה תמונה בגודל גדול (hero), אותה כותרת, אותו מחיר, ו"חזרה לרשימה".
  3. הוסיפו @view-transition { navigation: auto } ל-CSS הגלובלי.
  4. ב-products.html, לכל כרטיס הוסיפו inline styles: style="view-transition-name: product-{id}-image" על התמונה, product-{id}-title על הכותרת, product-{id}-price על המחיר.
  5. ב-product-{id}.html, הוסיפו את אותם שמות על ה-hero image, כותרת, ומחיר בעמוד הפרטים.
  6. הוסיפו CSS ל-group animation: ::view-transition-group(product-1-image) { animation-duration: 0.4s; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); } — חזרו על זה ל-4 המוצרים (או השתמשו ב-view-transition-class אם Chrome 125+).
  7. בדקו ב-Chrome: לחצו על כרטיס. התמונה, הכותרת והמחיר צריכים "לעוף" למיקומיהם בעמוד הפרטים.
  8. לחצו Back. ה-morph צריך לעבוד בכיוון ההפוך אוטומטית.
  9. הוסיפו reduced-motion fallback.
  10. בדקו ב-Safari 18 ו-Firefox — ודאו שהכל עובד (ב-Firefox בלי morph, אבל בלי שבירה).

מה צריך להיות בסוף: 5 עמודים (1 list + 4 details) עם morph transitions שעובדים בשני הכיוונים, 3 screenshots (תחילה מעבר, אמצע מעבר, סוף מעבר), ו-reduced-motion fallback תקין.

תרגיל 3: Astro Integration — Framework Setup אמיתי 25 דקות
  1. צרו פרויקט Astro חדש: npm create astro@latest. בחרו ב-template "Minimal".
  2. צרו 3 pages ב-src/pages/: index.astro, blog.astro, about.astro.
  3. צרו src/layouts/Layout.astro עם ה-HTML boilerplate.
  4. בתוך <head> של ה-Layout, הוסיפו: import { ViewTransitions } from 'astro:transitions'; ו-<ViewTransitions />.
  5. הוסיפו ב-CSS גלובלי את ה-reduced-motion fallback.
  6. ריצו npm run dev ופתחו ב-Chrome. נווטו בין העמודים — יהיה cross-fade אוטומטי.
  7. בחרו אלמנט בכל עמוד (למשל ה-h1). הוסיפו transition:name="page-title" בכל עמוד. עכשיו לוגו הכותרת "יזוז" בחלקות במעבר.
  8. הוסיפו פיצ'ר מתקדם: transition:persist על video או audio player — הוא ימשיך לנגן בזמן המעבר.
  9. בנו production build: npm run build. בדקו את ה-output של HTML — שימו לב ש-Astro מוסיף polyfill קטן שעובד גם ב-Safari 17.
  10. Deploy ל-Netlify/Vercel/Cloudflare Pages. בדקו על URL אמיתי ב-3 דפדפנים.

מה צריך להיות בסוף: אתר Astro עם View Transitions מובנים, URL חי להצגה, 3 screenshots מ-3 דפדפנים (Chrome, Safari, Firefox), ומסמך קצר שמתאר אילו פיצ'רים השתמשתם בהם (transition:name, transition:persist, ברירת-המחדל).

תרגיל 4: Reduced-Motion Fallback Audit 20 דקות
  1. קחו את כל הפרויקטים שיצרתם בתרגילים 1-3.
  2. הפעילו "Reduce motion" במערכת שלכם (macOS / Windows / iOS / Android — כל מה שיש לכם בהישג יד).
  3. עברו על כל פרויקט ובדקו: האם המעברים נעלמים? האם הניווט עדיין עובד? האם אין freeze או שגיאות?
  4. רשמו בטבלה: פרויקט | מעברים כבויים? | ניווט עובד? | שגיאות? | Status (PASS/FAIL).
  5. לכל FAIL — תקנו את ה-CSS. ודאו שכל ::view-transition-* מוגדר לבטל animation.
  6. בדקו גם עם prefers-reduced-motion: no-preference (ברירת-מחדל) שהאנימציות חוזרות.
  7. הריצו Lighthouse Accessibility score — ודאו שה-score הוא 100/100 (reduced-motion הוא חלק מ-accessibility).
  8. צלמו 2 video clips קצרים (10 שניות כל אחד): (א) עם reduced-motion off, (ב) עם reduced-motion on.
  9. העלו את ה-clips ל-Loom או YouTube unlisted, ושמרו את הקישורים.

מה צריך להיות בסוף: טבלת audit של 3 פרויקטים × 5 עמודות, 2 video clips משווים (motion on/off), ו-Lighthouse Accessibility score של 100 בכל פרויקט.

מסגרת החלטה: איזה סוג מעבר להשתמש
ContextTransitionWhy
Site-wide navigation (home, about, services)Cross-fadeברירת-מחדל מתאימה. לא מסיח את הדעת. מתאים לכל עמוד.
E-commerce: list → product detailMorph על תמונה + כותרת + מחיריוצר תחושת continuity. הגולש "עוקב" אחרי המוצר.
Blog: list → articleMorph על cover image בלבדקונטקסט שהכתבה היא הרחבה של ה-thumbnail.
Wizard / Onboarding / Checkout stepsSlide (horizontal)משדר "תהליך לינארי". הגולש יודע שמתקדם.
Dashboard: switching between sectionsCross-fade + persistent sidebarSidebar לא זז (view-transition-name: sidebar); main content מחליף.
Gallery: thumbnail → lightboxMorph על התמונה יחידהה-"hero moment" הקלאסי. תמונה גדלה למסך מלא.
Modal open/closeScale + fade (custom @keyframes)Modal הוא לא "עמוד", אז cross-fade חלש מדי. Scale נותן תחושת "מגיע ממקום מסוים".
Form submission → success pageCross-fade עם delay קצרמעבר חלק, אבל לא דרמטי. המטרה: confirmation, לא וואו.
שגרת עבודה: שדרוג אתרים עם View Transitions
תדירותמה לעשותכמה זמן
יומי גלשו ל-2 אתרים חדשים (מ-Awwwards, Muzli, או רשימה של daily inspiration). בדקו: האם יש להם View Transitions? אם כן — איזה סוג (cross-fade, morph, slide)? פתחו DevTools → Animations וצפו במעבר. אם לא — שאלו "איך הייתי מיישם morph פה?". 5 דקות
שבועי בנוסף לשגרה של פרקים 5-7 (Layout audit, Modern CSS check, Scroll animations): הוסיפו View Transition אחד לפרויקט אחד חי. או Cross-fade (5 דקות), או Morph על אלמנט אחד (20 דקות). בדקו ב-3 דפדפנים + reduced-motion. 30 דקות
חודשי עדכנו את ה-prompt templates האישיים שלכם ל-View Transitions. הוסיפו variations: wizard RTL, persistent sidebar, modal scale-fade. בדקו שה-Fallback Checklist עובד ב-100% בכל האתרים שלכם (Lighthouse + real devices). 45 דקות
אם אתם עושים רק דבר אחד מהפרק הזה

הוסיפו את 3 השורות האלה לקובץ ה-CSS הגלובלי של הפרויקט הכי חשוב שלכם ברגע זה: @view-transition { navigation: auto; } ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.25s; } @media (prefers-reduced-motion: reduce) { ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; } }. זה הכל. 3 שורות, 2 דקות. האתר שלכם ירגיש מייד 40% יותר "אפליקציה" — בלי לגעת בשום דבר אחר. ה-morph transitions ו-slide transitions הם בונוסים שאפשר להוסיף בהמשך, אבל ה-cross-fade הבסיסי הוא ה-80/20. אם תעשו רק את זה — כבר קיפצתם קפיצה שנראית יחסית לאיפה שהיו 99% מאתרי AI באפריל 2026.

בדקו את עצמכם — 5 שאלות
  1. מה ההבדל היסודי בין @keyframes ל-View Transitions API? תסבירו במשפט אחד. (רמז: @keyframes מניע אלמנט יחיד ממצב A ל-B; View Transitions מניע מעבר בין שני מצבי DOM שונים, כולל בין עמודים)
  2. למה view-transition-name חייב להיות ייחודי בכל רגע נתון? (רמז: הדפדפן צריך להתאים אלמנט "לפני" ל-"אחרי"; אם יש שניים עם אותו שם, ההתאמה נכשלת בשקט והמעבר נשבר)
  3. איך יודעים אם האתר שלכם הוא SPA או MPA, ולמה זה משנה ל-View Transitions? (רמז: SPA = ניווט בלי page reload, MPA = HTML חדש מהשרת; ל-SPA: document.startViewTransition(); ל-MPA: @view-transition { navigation: auto })
  4. למה מומלץ לתייג רק 1-3 אלמנטים עם view-transition-name? מה קורה עם 20? (רמז: קוגניטיבית העין לא יכולה לעקוב; 20 אלמנטים שזזים = כאוס ויזואלי; 2-3 = focal points ברורים)
  5. מה עושה prefers-reduced-motion: reduce, ולמה זה חובה ולא אופציונלי? (רמז: משתמשים עם motion sickness / accessibility needs; זו דרישת נגישות WCAG; 6 שורות CSS מספיקות לכיבוי כל ה-view transitions)
סיכום הפרק

בפרק הזה סגרתם את הפער האחרון שהופך אתר ל"אתר" במקום ל"אפליקציה": מעברי עמודים חלקים. ראיתם שהמרחק בין השניים, שעד 2023 היה 200 שורות JavaScript וספריות חיצוניות, הוא היום 3 שורות CSS. למדתם שלושה סוגי מעברים בסיסיים — Cross-fade (ברירת-מחדל, 3 שורות), Morph (shared element transition כמו App Store), ו-Slide (wizard-style, עם התאמה ל-RTL).

הבנתם את ה-building blocks של ה-API: document.startViewTransition() כנקודת הכניסה ב-JavaScript ל-SPAs; view-transition-name כ-CSS property שמסמן אלמנט כמשתתף במעבר, עם הכלל הקריטי של ייחודיות; 7 ה-::view-transition-* pseudo-elements שמאפשרים לעצב כל שכבה של המעבר ב-CSS; ו-@view-transition { navigation: auto } השורה המופלאה שמפעילה מעברים בין עמודים באתר MPA בלי שורת JavaScript אחת.

בחלק השני של הפרק הבחנתם בין Same-document transitions (SPA — React, Vue, Next.js client-side) ל-Cross-document transitions (MPA — Astro, static sites, Next.js App Router, WordPress) — ההבדל המושגי החשוב ביותר לפרויקט שלכם. קיבלתם decision framework מדויק לבחירה בין השניים, וטבלת שילוב ב-6 frameworks: Astro (1 שורה, מובנה), Next.js 15 (component experimental), React Router v7 (prop על Link), SvelteKit/Vue (wrapper ידני), ו-vanilla HTML (1 שורה CSS).

למדתם את מצב התמיכה באפריל 2026 — Chrome/Edge/Safari מלא, Firefox בדרך — ואת הפילוסופיה של progressive enhancement: View Transitions לא שובר שום דבר, אם אין תמיכה מקבלים ניווט רגיל. בנוסף, פיצחתם 5 Gotchas ש-99% מהמפתחים נתקלים בהם (display: none שובר morph; שמות זהים; mobile Safari stutter; window.location.href לא מפעיל מעבר; iframes לא נתמכים).

הכי חשוב — למדתם את 3 ה-AI Prompt Templates שהופכים בקשה עמומה ("add smooth transitions") לקוד production-ready: (א) Cross-fade עם reduced-motion fallback; (ב) Morph בין list view ל-detail view עם view-transition-name דינמיים לפי product id; (ג) Slide RTL לwizard 3-שלבי עם זיהוי כיוון ניווט. הפרומפטים האלה הם המפתח — לא הקוד, אלא היכולת לבקש את הקוד הנכון.

יש לכם עכשיו 4 deliverables מוחשיים: Cross-fade demo עובד, Morph transition על כרטיס מוצר, Slide wizard עם RTL, ורשימת frameworks עם ה-setup המדויק לכל אחד. Plus — 3 AI prompts מאומתים, Fallback Checklist של 6 פריטים, ומילון של 10 מונחים חדשים.

הגשר לפרק הבא: עד עכשיו בנינו את השכבות הבאות — Layout (פרק 5), Modern CSS primitives (פרק 6), Scroll animations (פרק 7), Page transitions (פרק 8). האתר שלכם כבר מתנהג כמו אפליקציה. בפרק 9 — "Glassmorphism, Liquid Glass, Aurora UI ומגמות עיצוב מודרניות" — נעבור ל-שכבת האפקטים: backdrop-filter: blur() שיוצר זכוכית חלבית; Apple Liquid Glass — הטרנד המרכזי של 2025-2026 עם שכבות של feTurbulence ו-feSpecularLighting; Aurora UI ו-mesh gradients אנימטיים; ומתי Neubrutalism מתאים ומתי הוא פשוט מכוער. אחרי פרק 9 יהיו לכם את כל השכבות של אתר מקצועי מ-2026 — לא רק "עובד" אלא "מרגיש כמו שסטודיו בנה אותו". View Transitions שבניתם בפרק 8 ישמשו בפרק 13 (capstone) כחלק מ-design brief מלא שתעבירו ל-AI.

צ'קליסט — מה צריך להיות מוכן לפני שממשיכים לפרק 9