לדלג לתוכן

1.8 אנימציות ומעברים הרצאה

מעברים - Transitions

מעברים מאפשרים לשנות ערך CSS בצורה חלקה לאורך זמן, במקום שהשינוי יקרה מיידית.
לדוגמה, כשמרחפים מעל כפתור והצבע שלו משתנה - transition גורם לשינוי להיות הדרגתי ולא קופצני.

תחביר בסיסי

.button {
  background: #3498db;
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  transition: background 0.3s ease;
}

.button:hover {
  background: #2980b9;
}

כשמרחפים על הכפתור, הצבע משתנה בצורה חלקה לאורך 0.3 שניות.

המאפיינים של transition

transition: property duration timing-function delay;
  • property - איזה מאפיין CSS לעבור (background, color, transform, וכו)
  • duration - כמה זמן המעבר (0.3s, 500ms)
  • timing-function - עקומת המהירות (ease, linear, וכו)
  • delay - עיכוב לפני תחילת המעבר

אפשר גם לכתוב כל מאפיין בנפרד:

.box {
  transition-property: background, transform;
  transition-duration: 0.3s, 0.5s;
  transition-timing-function: ease, ease-in-out;
  transition-delay: 0s, 0.1s;
}

מעבר על כל המאפיינים

.box {
  transition: all 0.3s ease;
}

all יחיל מעבר על כל מאפיין שמשתנה. זה נוח אבל פחות יעיל מבחינת ביצועים - עדיף לציין את המאפיינים הספציפיים.

מעבר על כמה מאפיינים

.card {
  background: white;
  transform: translateY(0);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.card:hover {
  transform: translateY(-5px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
}

הכרטיס "צף" כלפי מעלה ומקבל צל גדול יותר כשמרחפים עליו.


פונקציות תזמון - Timing Functions

פונקציות התזמון שולטות על מהירות השינוי לאורך זמן המעבר:

.box-1 { transition: transform 0.5s ease; }
.box-2 { transition: transform 0.5s linear; }
.box-3 { transition: transform 0.5s ease-in; }
.box-4 { transition: transform 0.5s ease-out; }
.box-5 { transition: transform 0.5s ease-in-out; }
  • ease - ברירת מחדל. מתחיל לאט, מאיץ, ומאט בסוף
  • linear - מהירות קבועה מתחילה ועד סוף
  • ease-in - מתחיל לאט ומאיץ
  • ease-out - מתחיל מהר ומאט
  • ease-in-out - מתחיל ומסיים לאט, מהיר באמצע

cubic-bezier - עקומה מותאמת אישית

.box {
  transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
}

cubic-bezier מאפשר ליצור עקומת מהירות מותאמת אישית. הדוגמה למעלה יוצרת אפקט "קפיצי" (overshoot).
אפשר להשתמש בכלי אונליין כמו cubic-bezier.com כדי לעצב עקומות ויזואלית.


טרנספורמציות - Transforms

transform מאפשר לשנות את המראה של אלמנט - להזיז, לסובב, לשנות גודל, ולהטות - בלי להשפיע על ה-layout (אלמנטים אחרים לא זזים).

הזזה - translate

.box {
  transform: translate(50px, 100px);  /* move right 50px, down 100px */
}

.box {
  transform: translateX(50px);  /* move right 50px */
}

.box {
  transform: translateY(-20px); /* move up 20px */
}

אפשר להשתמש באחוזים - שמתייחסים לגודל האלמנט עצמו:

.box {
  transform: translateX(50%); /* move right by half of its own width */
}

טריק מרכוז מוכר:

.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

סיבוב - rotate

.box {
  transform: rotate(45deg);   /* rotate 45 degrees clockwise */
}

.box {
  transform: rotate(-90deg);  /* rotate 90 degrees counter-clockwise */
}

שינוי גודל - scale

.box {
  transform: scale(1.5);      /* 150% of original size */
}

.box {
  transform: scale(0.5);      /* 50% of original size */
}

.box {
  transform: scaleX(2);       /* stretch horizontally to 200% */
}

.box {
  transform: scaleY(0.8);     /* shrink vertically to 80% */
}

הטיה - skew

.box {
  transform: skew(10deg);          /* skew on both axes */
}

.box {
  transform: skewX(10deg);        /* skew horizontally */
}

.box {
  transform: skewY(-5deg);        /* skew vertically */
}

transform-origin - נקודת המוצא

ברירת המחדל של transform היא מרכז האלמנט. אפשר לשנות:

.box {
  transform-origin: top left;     /* rotate/scale from top-left corner */
  transform: rotate(45deg);
}

.box {
  transform-origin: bottom center;
  transform: scale(1.5);
}

שילוב טרנספורמציות

אפשר לשלב כמה transforms בשורה אחת:

.box {
  transform: translateX(100px) rotate(45deg) scale(1.2);
}

שימו לב - הסדר חשוב. הtransforms מוחלים מימין לשמאל (מהסוף להתחלה).


שילוב transition עם transform

כאן קורה הקסם - שילוב של מעברים עם טרנספורמציות:

.card {
  transition: transform 0.3s ease;
}

.card:hover {
  transform: scale(1.05);
}

כרטיס שמתרחב בצורה חלקה כשמרחפים עליו.

.link {
  display: inline-block;
  transition: transform 0.2s ease;
}

.link:hover {
  transform: translateY(-3px);
}

קישור ש"קופץ" למעלה כשמרחפים עליו.

.icon {
  transition: transform 0.3s ease;
}

.icon:hover {
  transform: rotate(360deg);
}

אייקון שמסתובב סיבוב שלם כשמרחפים.


אנימציות - Animations

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

הגדרת אנימציה - @keyframes

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

או עם אחוזים ליותר שליטה:

@keyframes bounce {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-30px);
  }
  100% {
    transform: translateY(0);
  }
}

אפשר להגדיר כמה שלבים שרוצים:

@keyframes colorChange {
  0%   { background: red; }
  25%  { background: yellow; }
  50%  { background: green; }
  75%  { background: blue; }
  100% { background: red; }
}

הפעלת אנימציה

.element {
  animation-name: fadeIn;
  animation-duration: 1s;
}

כל מאפייני האנימציה

.element {
  animation-name: bounce;              /* which keyframes to use */
  animation-duration: 0.6s;            /* how long one cycle takes */
  animation-timing-function: ease;     /* speed curve */
  animation-delay: 0.2s;              /* wait before starting */
  animation-iteration-count: 3;        /* how many times to repeat */
  animation-direction: alternate;      /* play direction */
  animation-fill-mode: forwards;       /* what to do when done */
}

animation-iteration-count

.spinner {
  animation-iteration-count: infinite; /* never stops */
}

.pulse {
  animation-iteration-count: 3;        /* plays 3 times */
}

animation-direction

.element { animation-direction: normal; }    /* 0% -> 100% */
.element { animation-direction: reverse; }   /* 100% -> 0% */
.element { animation-direction: alternate; } /* 0% -> 100% -> 0% -> 100%... */
.element { animation-direction: alternate-reverse; } /* 100% -> 0% -> 100%... */

alternate מצוין לאנימציות שחוזרות - האנימציה רצה קדימה ואחורה ונראית חלקה.

animation-fill-mode

שולט על מה קורה לפני ואחרי האנימציה:

.element { animation-fill-mode: none; }      /* default - returns to original state */
.element { animation-fill-mode: forwards; }  /* keeps the last keyframe */
.element { animation-fill-mode: backwards; } /* applies first keyframe during delay */
.element { animation-fill-mode: both; }      /* combines forwards and backwards */

forwards הוא הכי נפוץ - אם אלמנט עושה fade-in, רוצים שהוא ישאר גלוי בסוף.

קיצור - animation shorthand

.element {
  animation: bounce 0.6s ease 0.2s 3 alternate forwards;
  /* name | duration | timing | delay | count | direction | fill-mode */
}

כמה אנימציות על אלמנט אחד

.element {
  animation:
    fadeIn 1s ease forwards,
    slideUp 1s ease 0.3s forwards;
}

דוגמאות מעשיות

ספינר טעינה - Loading Spinner

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #eee;
  border-top-color: #3498db;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

linear חשוב כאן כי אנחנו רוצים סיבוב במהירות קבועה.

אפקט פעימה - Pulse

@keyframes pulse {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(52, 152, 219, 0.7);
  }
  70% {
    transform: scale(1.05);
    box-shadow: 0 0 0 15px rgba(52, 152, 219, 0);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(52, 152, 219, 0);
  }
}

.pulse-btn {
  animation: pulse 2s ease infinite;
}

אפקט הופעה - Fade In Up

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.card {
  animation: fadeInUp 0.6s ease forwards;
}

/* stagger - each card appears with a delay */
.card:nth-child(1) { animation-delay: 0.1s; }
.card:nth-child(2) { animation-delay: 0.2s; }
.card:nth-child(3) { animation-delay: 0.3s; }
.card:nth-child(4) { animation-delay: 0.4s; }
  • כל כרטיס מופיע עם עיכוב קצת יותר גדול - יוצר אפקט "גל" מרשים

אפקט הקלדה - Typing

@keyframes typing {
  from {
    width: 0;
  }
  to {
    width: 20ch; /* ch = width of "0" character */
  }
}

@keyframes blink {
  50% {
    border-color: transparent;
  }
}

.typing-text {
  font-family: monospace;
  font-size: 1.5rem;
  overflow: hidden;
  white-space: nowrap;
  border-right: 3px solid black;
  width: 0;
  animation:
    typing 3s steps(20) forwards,
    blink 0.7s step-end infinite;
}

steps(20) גורם לאנימציה להתקדם ב-20 צעדים בדידים - כאילו מישהו מקליד אות אחרי אות.


ביצועים - Performance

לא כל מאפייני CSS שווים מבחינת ביצועים. חשוב לדעת מה לאנימציה ומה לא.

מה כן לאנימציה

/* these are GPU-accelerated - smooth on any device */
transform: translate(), rotate(), scale()
opacity

שני המאפיינים האלו מעובדים ב-GPU (כרטיס המסך) ולא גורמים לדפדפן לחשב מחדש את ה-layout. התוצאה: אנימציה חלקה ב-60fps.

מה לא לאנימציה

/* these cause layout recalculation - avoid animating */
width, height
margin, padding
top, left, right, bottom
font-size
border-width

שינוי של המאפיינים האלו מכריח את הדפדפן לחשב מחדש את המיקום של כל האלמנטים בעמוד - מה שגורם לגמגום.

הכלל החשוב

במקום לאנימציה של left או top, השתמשו ב-transform: translate():

/* bad - causes layout recalculation */
.box {
  position: absolute;
  left: 0;
  transition: left 0.3s ease;
}
.box:hover {
  left: 100px;
}

/* good - GPU accelerated */
.box {
  transition: transform 0.3s ease;
}
.box:hover {
  transform: translateX(100px);
}

במקום לאנימציה של width או height, השתמשו ב-transform: scale():

/* bad */
.box { transition: width 0.3s; }
.box:hover { width: 200px; }

/* good */
.box { transition: transform 0.3s; }
.box:hover { transform: scaleX(1.5); }

will-change

.animated-element {
  will-change: transform, opacity;
}

will-change מודיע לדפדפן מראש שהאלמנט הולך להשתנות - הדפדפן יכול להיערך ולהקצות משאבי GPU מראש.

שימו לב: אל תשימו will-change על כל דבר - זה צורך זכרון. השתמשו בו רק על אלמנטים שבאמת מאונימציים.

נגישות - prefers-reduced-motion

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

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

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

אפשר גם לגשת לזה הפוך - להפעיל אנימציות רק למי שלא ביקש להפחית:

.card {
  opacity: 1; /* default - no animation */
}

@media (prefers-reduced-motion: no-preference) {
  .card {
    animation: fadeIn 0.5s ease forwards;
  }
}

סיכום

  • transitions - שינויים חלקים בין שני מצבים, בדרך כלל על hover
  • transforms - שינוי מראה: הזזה, סיבוב, שינוי גודל, הטיה
  • animations - שינויים מורכבים עם keyframes, יכולים לרוץ אוטומטית ולחזור
  • ביצועים - אנימציה רק transform ו-opacity, לא width/height/margin
  • נגישות - תמיד כבדו את prefers-reduced-motion
  • שילוב של transition + transform נותן אנימציות מעולות לinteraction
  • שילוב של animation + transform נותן אפקטים מורכבים כמו ספינרים ואפקטי הופעה