תנועה

  • אפשר להשתמש ב-clip-path וב-mask-image כדי ליצור חשיפות גיאומטריות בהתאמה אישית ודעיכות חלקות.
  • כדאי להשתמש באנימציות מבוססות-גלילה (animation-timeline: scroll()) לאפקטים לא חיוניים שקשורים לגלילה, במקום במאזינים של JS.
  • אפשר להשתמש במעברי תצוגה כדי ליצור אנימציה בין מצבי פריסה מורכבים בצורה חלקה.

ביצועים

.popover-reveal {
  /* Transition discrete display and top-layer overlay alongside opacity */
  transition:
    opacity ease-out,
    display,
    overlay;
  transition-duration: 0.2s;
  transition-behavior: allow-discrete;
}

נגישות

משתמשים בשאילתות מדיה של prefers-reduced-motion כדי להשבית תנועה כבדה למשתמשים שמעדיפים זאת.

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

אל תפעילו את animation-duration: 0.01ms; באופן גלובלי, כי זה עלול לגרום לאנימציות מסוימות להיראות יותר צורמות. במקום זאת, צריך לטפל בהעדפות התנועה בכל מקרה לגופו באמצעות אחת משתי הגישות, ולהטמיע את השאילתה @media בתוך הכלל כדי ששתי הגרסאות יישמרו יחד:

  • מתחילים עם אנימציות שמופעלות כברירת מחדל, ומפחיתים אותן באמצעות @media (prefers-reduced-motion: reduce):
/* Good: Dampen spin states or slow down animations for reduced motion */
.spinner {
  animation: spin 1s linear infinite;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
    opacity: 0.5;
  }
}

progress:not([value]) {
  animation: slide 1s infinite linear;
  @media (prefers-reduced-motion: reduce) {
    animation-duration: 20s;
  }
}
  • כדי להתחיל בלי אנימציות כברירת מחדל, ולהפעיל אותן באמצעות @media (prefers-reduced-motion: no-preference):
/* Good: Default to static or gentle states and opt-in to full motion */
.spinner {
  opacity: 0.5;
  @media (prefers-reduced-motion: no-preference) {
    opacity: 1;
    animation: spin 1s linear infinite;
  }
}

progress:not([value]) {
  animation: slide 20s infinite linear;
  @media (prefers-reduced-motion: no-preference) {
    animation-duration: 1s;
  }
}

עבודה עם אירועי אנימציה ומעבר ב-JavaScript

גם בממשק AnimationEvent (animationstart, animationiteration, animationend, animationcancel) וגם בממשק TransitionEvent (transitionrun, transitionstart, transitionend, transitioncancel), event.target מספק את רכיב ה-DOM המקורי. כדי לגשת לאובייקט Animation הספציפי (Animation,‏ CSSAnimation או CSSTransition) שהפעיל את האירוע, משתמשים במאפיין event.animation לקריאה בלבד.

אם event.animation לא זמין, בדרך כלל אפשר למצוא את המופע של Animation על ידי קריאה ל-event.target.getAnimations() וסינון לפי event.animationName (או event.propertyName למעברים). עם זאת, עדיף להשתמש ישירות ב-event.animation כדי להימנע מכמה תרחישים שבהם ברירת המחדל הזו שמסננת את event.target.getAnimations() לא פועלת כצפוי:

  • לאנימציות של Web Animations API (element.animate()) אין animationName, ולכן אי אפשר להתאים אותן לפי שם כשמסננים את event.target.getAnimations().
  • סינון לפי animationName עבור AnimationEvents הוא לא חד-משמעי כשיש כמה אנימציות עם אותו שם שמצורפות לאותו רכיב.
    • שימו לב שהסינון לפי transitionProperty עבור TransitionEvent פועל כי יש רק אירוע אחד לכל מאפיין מעבר.
  • המאפיין event.target תמיד מצביע על רכיב ה-DOM המקורי, כך שהוא לא מבחין בין אנימציות שפועלות על הרכיב עצמו לבין אחד מרכיבי הפסאודו שלו, ואילו event.animation.effect.pseudoElement חושף את רכיב הפסאודו של היעד ישירות.
// Works in most basic CSS animation cases, but fails for WAAPI animations,
// duplicate animation names on the same element, or pseudo-elements.
document.addEventListener('animationstart', (event) => {
  const animation = event.target
    .getAnimations()
    .find((anim) => anim.animationName === event.animationName);
  console.log(animation);
});

// PREFERRED: Directly access the exact Animation object via event.animation
document.addEventListener('animationstart', (event) => {
  const animation = event.animation;
  console.log(animation);
});

אפשר לזהות תמיכה בתכונות באמצעות 'animation' in AnimationEvent.prototype (או 'animation' in TransitionEvent.prototype).