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¶
- 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;
}
מעבר על כל המאפיינים¶
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 - עקומה מותאמת אישית¶
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 */
}
אפשר להשתמש באחוזים - שמתייחסים לגודל האלמנט עצמו:
טריק מרכוז מוכר:
סיבוב - 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 בשורה אחת:
שימו לב - הסדר חשוב. הtransforms מוחלים מימין לשמאל (מהסוף להתחלה).
שילוב transition עם transform¶
כאן קורה הקסם - שילוב של מעברים עם טרנספורמציות:
כרטיס שמתרחב בצורה חלקה כשמרחפים עליו.
.link {
display: inline-block;
transition: transform 0.2s ease;
}
.link:hover {
transform: translateY(-3px);
}
קישור ש"קופץ" למעלה כשמרחפים עליו.
אייקון שמסתובב סיבוב שלם כשמרחפים.
אנימציות - Animations¶
אנימציות מאפשרות שינויים מורכבים יותר ממעברים - הן יכולות לרוץ אוטומטית, לחזור, ולכלול מספר שלבים.
הגדרת אנימציה - @keyframes¶
או עם אחוזים ליותר שליטה:
@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: 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 */
}
כמה אנימציות על אלמנט אחד¶
דוגמאות מעשיות¶
ספינר טעינה - 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¶
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 נותן אפקטים מורכבים כמו ספינרים ואפקטי הופעה