שליטה ברמת פירוט גבוהה יותר על טרנספורמציות CSS עם מאפייני טרנספורמציה נפרדים

טרנספורמציה של רכיבים באמצעות המאפיינים translate,‏ rotate ו-scale

המאפיין transform ב-CSS

כדי להחיל טרנספורמציות על רכיב, משתמשים בנכס transform של CSS. הנכס מקבל <transform-function> אחד או יותר, שחלים זה אחרי זה.

.target {
  transform: translateX(50%) rotate(30deg) scale(1.2);
}

הרכיב המטורגט מוסט ב-50% על ציר X, מסובב ב-30 מעלות ולבסוף מוגדל ל-120%.

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

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

.target:hover {
  transform: translateX(50%) rotate(30deg) scale(2); /* Only the value of scale() changed */
}

מאפייני הטרנספורמציה הנפרדים

מאפיינים נפרדים לטרנספורמציות CSS נשלחים עם Chrome 104. המאפיינים הם scale,‏ rotate ו-translate, שאפשר להשתמש בהם כדי להגדיר בנפרד את החלקים האלה של טרנספורמציה.

כך, Chrome מצטרף ל-Firefox ול-Safari שכבר תומכים בנכסים האלה.

תמיכה בדפדפנים

  • Chrome: ‏ 104.
  • Edge: ‏ 104.
  • Firefox: 72.
  • Safari: ‏ 14.1.

מקור

כשמעתיקים מחדש את הדוגמה הקודמת של transform עם המאפיינים הנפרדים, קטע הקוד הופך כך:

.target {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

סדר העניינים

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

כשמשתמשים ב-transform, פונקציות הטרנספורמציה חלות בסדר שבו הן נכתבות – משמאל (בחוץ) לימין (בפנים).

כשמשתמשים במאפייני טרנספורמציה ספציפיים, הסדר הוא לא הסדר שבו הם מוצהרים. הסדר הוא תמיד זהה: קודם translate (בחוץ), אחר כך rotate ואז scale (בפנים).

כלומר, שני קטעי הקוד הבאים מניבים את אותה תוצאה:

.transform--individual {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

.transform--individual-alt {
  rotate: 30deg;
  translate: 50% 0;
  scale: 1.2;
}

בשני המקרים, הרכיבים המטורגטים יועברו קודם ב-50% על ציר X, לאחר מכן יתבצעו בהם סיבוב ב-30deg ולבסוף יתבצע שינוי קנה המידה שלהם ב-1.2.

אם אחד ממאפייני הטרנספורמציה הספציפיים מוצהר יחד עם מאפיין transform, הטרנספורמציות הספציפיות חלות קודם (translate,‏ rotate ואז scale) והמאפיין transform חל אחרון (בפנים). פרטים נוספים מופיעים במפרט שמגדיר איך צריך לחשב את מטריצת הטרנספורמציה.

אנימציות

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

תרשים של תמונות מפתח (keyframe).

שימוש ב-transform

כדי להטמיע את האנימציה הזו באמצעות transform, צריך לחשב את כל הערכים שבין הערכים הקיצוניים לכל הטרנספורמציות שהוגדרו, ולכלול אותם בכל keyframe. לדוגמה, כדי לבצע רוטציה בנקודה של 10%, צריך לחשב גם את הערכים של שאר הטרנספורמציות, כי כל הערכים האלה נדרשים למאפיין transform.

תרשים של פריימים מרכזיים עם ערכי ביניים מחושבים.

קוד ה-CSS שייווצר יהיה:

@keyframes anim {
  0% { transform: translateX(0%); }
  5% { transform: translateX(5%) rotate(90deg) scale(1.2); }
  10% { transform: translateX(10%) rotate(180deg) scale(1.2); }
  90% { transform: translateX(90%) rotate(180deg) scale(1.2); }
  95% { transform: translateX(95%) rotate(270deg) scale(1.2); }
  100% { transform: translateX(100%) rotate(360deg); }
}

.target {
  animation: anim 2s;
  animation-fill-mode: forwards;
}

שימוש במאפייני טרנספורמציה נפרדים

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

@keyframes anim {
  0% { translate: 0% 0; }
  100% { translate: 100% 0; }

  0%, 100% { scale: 1; }
  5%, 95% { scale: 1.2; }

  0% { rotate: 0deg; }
  10%, 90% { rotate: 180deg; }
  100% { rotate: 360deg; }
}

.target {
  animation: anim 2s;
  animation-fill-mode: forwards;
}

שימוש במאפייני טרנספורמציה נפרדים ובכמה נקודות מפתח

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

@keyframes move {
  0% { translate: 0% 0; }
  100% { translate: 100% 0; }
}

@keyframes scale {
  0%, 100% { scale: 1; }
  5%, 95% { scale: 1.2; }
}

@keyframes rotate {
  0% { rotate: 0deg; }
  10%, 90% { rotate: 180deg; }
  100% { rotate: 360deg; }
}

.target {
  animation: move 2s, scale 2s, rotate 2s;
  animation-fill-mode: forwards;
}

בזכות הפיצול הזה, אפשר להחיל כל קבוצה נפרדת של נקודות מפתח כרצונכם, כי מאפייני transform – שהפכו עכשיו לנכסים נפרדים – כבר לא מחליפים זה את זה. בנוסף, אפשר לתת לכל טרנספורמציה תזמון שונה בלי שתצטרכו לכתוב מחדש את הכול.

ביצועים

אנימציות שמשתמשות בנכסים החדשים האלה יעילות באותה מידה כמו אנימציות של הנכס הקיים transform.

אנימציות של translate,‏ rotate ו-scale פועלות במעבד הקומפוזיציה באותו אופן שבו פועלות אנימציות של transform, כך שהן מתאימות לביצועים של אנימציות באותו אופן שבו transform מתאים.

הנכסים החדשים האלה פועלים גם עם הנכס will-change. באופן כללי, מומלץ להימנע משימוש מוגזם ב-will-change. לשם כך, צריך להשתמש בו במספר המינימלי של הרכיבים הנדרשים, ולמשך פרק הזמן הקצר ביותר האפשרי. עם זאת, כדאי גם להיות ספציפיים ככל האפשר. לדוגמה, אם אתם משתמשים ב-will-change כדי לבצע אופטימיזציה של אנימציה באמצעות המאפיינים rotate ו-filter, עליכם להצהיר על כך באמצעות will-change: rotate, filter. השיטה הזו טובה יותר מאשר שימוש ב-will-change: transform, filter במקרה שבו אתם יוצרים אנימציה של rotate ו-filter, כי חלק ממבני הנתונים ש-Chrome יוצר מראש כשמשתמשים ב-will-change שונים עבור transform לעומת rotate.

חלק מהסדרה 'חדשים עם יכולת פעולה הדדית'