תנועה היא חלק מרכזי בכל חוויה דיגיטלית, והיא מנחה את המשתמש מאינטראקציה אחת לאחרת. עם זאת, יש כמה פערים באנימציות חלקות בפלטפורמת האינטרנט. הרכיבים האלה כוללים את היכולת להוסיף אנימציה בקלות לאנימציות כניסה ויציאה, ואנימציה חלקה אל השכבה העליונה וממנה, כדי להציג רכיבים שניתן לסגור, כמו תיבות דו-שיח וחלונות קופצים.
כדי למלא את הפערים האלה, גרסאות Chrome 116 ו-117 כוללות ארבע תכונות חדשות בפלטפורמת האינטרנט, שמאפשרות אנימציות ומעברים חלקים לנכסים נפרדים.
ארבע התכונות החדשות האלה כוללות:
- היכולת ליצור אנימציה של
display
ו-content-visibility
בציר הזמן של נקודות מפתח (החל מגרסה 116 של Chrome). - המאפיין
transition-behavior
עם מילת המפתחallow-discrete
כדי לאפשר מעברים של נכסים נפרדים כמוdisplay
(מ-Chrome 117). - הכלל
@starting-style
להנפשה של אפקטים של כניסה מ-display: none
אל השכבה העליונה (החל מ-Chrome 117). - המאפיין
overlay
כדי לשלוט בהתנהגות של השכבה העליונה במהלך אנימציה (החל מ-Chrome 117).
הצגת אנימציות בתמונות מפתח
החל מגרסה 116 של Chrome, אפשר להשתמש ב-display
וב-content-visibility
בכללי keyframe. לאחר מכן, הם יוחלפו בזמן שמתרחש פריים המפתח. אין צורך בערכים חדשים נוספים כדי לתמוך בכך:
.card {
animation: fade-out 0.5s forwards;
}
@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}
בדוגמה הקודמת, האטימות משתנה לאפס במהלך 0.5 שניות, ואז מוגדר לה הצגה כ'ללא'. בנוסף, מילת המפתח forwards
מבטיחה שהאנימציה תישאר במצב הסופי שלה, כך שהרכיב שאליו היא חלה יישאר בסטטוסים display: none
ו-opacity: 0
.
זוהי דוגמה פשוטה שממחישה מה אפשר לעשות באמצעות מעבר (ראו הדגמה בקטע 'מעבר'). עם זאת, לא ניתן ליצור באמצעות מעברים אנימציות מורכבות יותר, כמו בדוגמה הבאה:
.card {
animation: spin-and-delete 1s ease-in forwards;
}
@keyframes spin-and-delete {
0% {
transform: rotateY(0);
filter: hue-rotate(0);
}
80% {
transform: rotateY(360deg);
filter: hue-rotate(180deg);
opacity: 1;
}
100% {
opacity: 0;
display: none;
}
}
אנימציית spin-and-delete
היא אנימציית יציאה. בשלב הראשון, הכרטיס יסתובב על ציר ה-Y, יתבצע סיבוב של גוון וב-80%
לאורך ציר הזמן, האטימות שלו תשתנה מ-1 ל-0. בסוף, הכרטיס מוחלף מ-display: block
ל-display: none
.
באנימציות היציאה האלה, במקום להחיל אותן ישירות על רכיב, אפשר להגדיר טריגר לאנימציות. לדוגמה, אפשר לצרף מאזין לאירועים ללחצן שמפעיל מחלקה כדי להחיל את האנימציה, כך:
.spin-out {
animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
document.querySelector('.card').classList.add('spin-out');
})
בדוגמה שלמעלה יש עכשיו מדינת סיום display:none
. יש הרבה מקרים שבהם כדאי להמשיך הלאה ולהסיר את צומת ה-DOM עם זמן קצוב לתפוגה כדי לאפשר לאנימציה להסתיים קודם.
מעבר בין אנימציות נפרדות
בניגוד ליצירת אנימציה של מאפיינים נפרדים באמצעות פריימים מרכזיים, כדי לבצע מעבר בין מאפיינים נפרדים צריך להשתמש במצב התנהגות המעבר allow-discrete
.
הנכס transition-behavior
המצב allow-discrete
מאפשר מעבר דיסקרטי, והוא ערך של המאפיין transition-behavior
. transition-behavior
מקבל שני ערכים: normal
ו-allow-discrete
.
.card {
transition: opacity 0.25s, display 0.25s;
transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */
}
.card.fade-out {
opacity: 0;
display: none;
}
גם הקיצור transition
מגדיר את הערך הזה, כך שאפשר להשמיט את המאפיין ולהשתמש במקום זאת במילת המפתח allow-discrete
בסוף הקיצור transition
בכל מעבר.
.card {
transition: opacity 0.5s, display 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
אם מוסיפים אנימציה למספר נכסים נפרדים, צריך לכלול את המאפיין allow-discrete
אחרי כל נכס שרוצים להוסיף לו אנימציה. לדוגמה:
.card {
transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
הכלל @starting-style
לאנימציות כניסה
עד עכשיו המאמר הזה כולל אנימציות יציאה. כדי ליצור אנימציות של כניסה, צריך להשתמש בכלל @starting-style
.
משתמשים ב-@starting-style
כדי להחיל סגנון שהדפדפן יכול לחפש לפני שהרכיב נפתח בדף. זהו המצב 'לפני הפתיחה' (המצב שממנו מתחילה האנימציה).
/* 0. IS-OPEN STATE */
/* The state at which the element is open + transition logic */
.item {
height: 3rem;
display: grid;
overflow: hidden;
transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete;
}
/* 1. BEFORE-OPEN STATE */
/* Starting point for the transition */
@starting-style {
.item {
opacity: 0;
height: 0;
}
}
/* 2. EXITING STATE */
/* While it is deleting, before DOM removal in JS, apply this
transformation for height, opacity, and a transform which
skews the element and moves it to the left before setting
it to display: none */
.is-deleting {
opacity: 0;
height: 0;
display: none;
transform: skewX(50deg) translateX(-25vw);
}
עכשיו יש לכם גם מצב כניסה וגם מצב יציאה לפריטים האלה ברשימת המשימות:
אנימציה של רכיבים אל השכבה העליונה וממנה
כדי להוסיף אנימציה לרכיבים מהשכבה העליונה, צריך לציין את המאפיין @starting-style
במצב 'פתיחה' כדי להגדיר לדפדפן מאיפה ליצור את האנימציה. בתיבת דו-שיח, המצב הפתוח מוגדר באמצעות המאפיין [open]
. כדי ליצור חלון קופץ, משתמשים בפסאודו-מחלקה :popover-open
.
דוגמה פשוטה לתיבת דו-שיח עשויה להיראות כך:
/* 0. IS-OPEN STATE */
dialog[open] {
translate: 0 0;
}
/* 1. BEFORE-OPEN STATE */
@starting-style {
dialog[open] {
translate: 0 100vh;
}
}
/* 2. EXIT STATE */
dialog {
transition: translate 0.7s ease-out, overlay 0.7s ease-out allow-discrete, display 0.7s ease-out allow-discrete;
translate: 0 100vh;
}
בדוגמה הבאה, ההשפעות של הכניסה והיציאה שונות. כדי להיכנס, מפעילים אנימציה מלמטה למעלה בחלון התצוגה, ומסיימים את האפקט בחלק העליון של חלון התצוגה. הוא נכתב גם באמצעות CSS בתצוגת עץ, כדי לאפשר אנקפסולציה חזותית טובה יותר.
כשאתם יוצרים אנימציה של חלון קופץ, צריך להשתמש בפסאודו-סיווג :popover-open
במקום במאפיין open
ששימש בעבר.
.settings-popover {
&:popover-open {
/* 0. IS-OPEN STATE */
/* state when popover is open, BOTH:
what we're transitioning *in* to
and transitioning *out* from */
transform: translateY(0);
opacity: 1;
/* 1. BEFORE-OPEN STATE */
/* Initial state for what we're animating *in* from,
in this case: goes from lower (y + 20px) to center */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
}
/* 2. EXIT STATE */
/* Initial state for what we're animating *out* to ,
in this case: goes from center to (y - 50px) higher */
transform: translateY(-50px);
opacity: 0;
/* Enumerate transitioning properties,
including display and allow-discrete mode */
transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}
מלון אחד (overlay
)
לבסוף, כדי להעביר את popover
או dialog
לשלב הדעיכה בשכבה העליונה, מוסיפים את הנכס overlay
לרשימת המעברים. popover
ו-dialog
גורמים לבריחה (escape) של קליפ אב וטרנספורמציות של אב, וגם מעבירים את התוכן לשכבה העליונה. אם לא תבצעו את המעבר overlay
, הרכיב יחזור מיד להיות חתוך, מעוצב ומכוסה, ולא תראו את המעבר מתבצע.
[open] {
transition: opacity 1s, display 1s allow-discrete;
}
במקום זאת, צריך לכלול את overlay
במעבר או באנימציה כדי להוסיף אנימציה ל-overlay
, יחד עם שאר התכונות, ולוודא שהוא יישאר בשכבה העליונה בזמן האנימציה. התמונה תהיה חלקה יותר.
[open] {
transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}
בנוסף, כשיש מספר רכיבים פתוחים בשכבה העליונה, שכבת-העל עוזרת לכם לשלוט במעבר החלק בתוך השכבה העליונה ומחוצה לה. אפשר לראות את ההבדל בדוגמה הפשוטה הזו. אם לא מחילים את overlay
על חלון הקופץ השני בזמן ההעברה שלו החוצה, הוא יזוז קודם מהשכבה העליונה, יקפוץ מאחורי חלון הקופץ השני, ואז יתחיל את המעבר. זה לא אפקט חלק במיוחד.
הערה לגבי מעברים בין תצוגות
אם אתם מבצעים שינויים ב-DOM, כמו הוספה והסרה של רכיבים מה-DOM, פתרון מצוין נוסף ליצירת אנימציות חלקות הוא מעבר בין תצוגות. ריכזנו כאן שתי דוגמאות מהדוגמאות שלמעלה שנוצרו באמצעות מעברים בין תצוגות.
בדמו הראשון הזה, במקום להגדיר את @starting-style
וטרנספורמציות CSS אחרות, מעברי התצוגה יטפלו במעבר. כך מגדירים את המעבר בין התצוגות:
קודם כול, ב-CSS, נותנים לכל כרטיס view-transition-name
נפרד.
.card-1 {
view-transition-name: card-1;
}
.card-2 {
view-transition-name: card-2;
}
/* etc. */
לאחר מכן, ב-JavaScript, עוטפים את המוטציה של DOM (במקרה הזה, הסרת הכרטיס) במעבר תצוגה.
deleteBtn.addEventListener('click', () => {
// Check for browser support
if (document.startViewTransition) {
document.startViewTransition(() => {
// DOM mutation
card.remove();
});
}
// Alternative if no browser support
else {
card.remove();
}
})
עכשיו הדפדפן יכול להתמודד עם דהייה ושינוי של כל כרטיס למיקום החדש שלו.
דוגמה נוספת למקרה שבו האפשרות הזו יכולה להיות שימושית היא הדגמה של הוספה/הסרה של פריטים ברשימה. במקרה כזה, חשוב לזכור להוסיף view-transition-name
ייחודי לכל כרטיס שנוצר.
סיכום
התכונות החדשות האלה בפלטפורמה מקריבות אותנו עוד יותר ליצירת אנימציות חלקות של כניסה ויציאה בפלטפורמת האינטרנט. מידע נוסף זמין בקישורים הבאים: