- カスタムの幾何学的な表示とスムーズなフェードアウトには、
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 メディアクエリを使用して、激しい動きを好まないユーザーに対して激しい動きをオフにします。
- 一時停止メカニズムを提供する: ユーザーが自動実行されるカルーセル、バナー、その他の永続的なアニメーションを停止できるようにします。
- デフォルトで静的ビューにする: デフォルトで静的状態にし、ユーザーがモーションを有効にできるようにすることを検討します。
- フラッシュの制限(1 秒間に 3 回)を超えないようにする: 明暗の急速な点滅は含めないでください。このような影響により、発作が引き起こされることがあります。
animation-duration: 0.01ms; をグローバルに適用しないでください。特定のアニメーションがより不快になる可能性があります。代わりに、2 つの方法のいずれかを使用して、モーション設定をケースバイケースで処理します。@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 が利用できない場合は、通常、event.target.getAnimations() を呼び出して event.animationName(または遷移の場合は event.propertyName)でフィルタリングすることで、Animation インスタンスを見つけることができます。ただし、event.target.getAnimations() をフィルタするこのフォールバックが想定どおりに動作しないシナリオを回避するため、event.animation を直接使用することをおすすめします。
- ウェブ アニメーション API(
element.animate())のアニメーションにはanimationNameがないため、event.target.getAnimations()をフィルタする際に名前で照合できません。 - 同じ名前の複数のアニメーションが同じ要素にアタッチされている場合、
AnimationEventのanimationNameによるフィルタリングは曖昧になります。TransitionEventのtransitionPropertyでのフィルタリングは、遷移プロパティごとに 1 つのイベントしかないため機能します。
event.targetは常に元の DOM 要素を指すため、要素自体で実行されているアニメーションとその擬似要素の 1 つで実行されているアニメーションを区別しません。一方、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)を使用して、サポートを機能検出できます。