मोशन

  • कस्टम ज्यामितीय रिवील और स्मूद फ़ेड-आउट के लिए, clip-path और mask-image का इस्तेमाल करें.
  • JS लिसनर के बजाय, स्क्रोल करने पर दिखने वाले गैर-ज़रूरी इफ़ेक्ट के लिए, स्क्रोल-ड्रिवन ऐनिमेशन (animation-timeline: scroll()) का इस्तेमाल करें.
  • व्यू ट्रांज़िशन का इस्तेमाल करके, मुश्किल लेआउट के बीच आसानी से ऐनिमेशन बनाएं.

परफ़ॉर्मेंस

  • opacity और transform को ऐनिमेट करें. इनमें अलग-अलग ट्रांसफ़ॉर्म प्रॉपर्टी भी शामिल हैं. उदाहरण के लिए, left/right/top/bottom के बजाय translate को ऐनिमेट करें. इससे यह पक्का किया जा सकेगा कि ऐनिमेशन, कंपोज़िटर थ्रेड पर बने रहें.
  • एंट्री और एग्ज़िट की अलग-अलग स्थितियों को नेटिव तौर पर ऐनिमेट करने के लिए, transition-behavior: allow-discrete, @starting-style, और (<dialog> या [popover] जैसे टॉप-लेयर एलिमेंट के लिए) overlay का इस्तेमाल करें. ज़्यादा जानकारी के लिए, एलिमेंट की एंट्री और एग्ज़िट को ऐनिमेट करना और एलिमेंट को टॉप लेयर में और उससे बाहर ऐनिमेट करना देखें.
.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 आपको ओरिजनल डीओएम एलिमेंट देता है. इवेंट को ट्रिगर करने वाले खास 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() को फ़िल्टर करते समय, उन्हें नाम से मैच नहीं किया जा सकता.
  • AnimationEvent के लिए animationName के हिसाब से फ़िल्टर करने पर, साफ़ तौर पर जानकारी नहीं मिलती. ऐसा तब होता है, जब एक ही एलिमेंट में एक ही नाम के कई ऐनिमेशन अटैच किए गए हों.
    • ध्यान दें कि TransitionEvent के लिए transitionProperty पर फ़िल्टर करने की सुविधा काम करती है, क्योंकि हर ट्रांज़िशन प्रॉपर्टी के लिए सिर्फ़ एक इवेंट होता है.
  • 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) का इस्तेमाल करके, यह पता लगाया जा सकता है कि ब्राउज़र में यह सुविधा काम करती है या नहीं.