CSS animation-composition で複数アニメーションを合成する方法

2026.04.21 09:00
2026.03.16 13:33
CSS animation-composition で複数アニメーションを合成する方法

CSSで複数のアニメーションを同時にかけたいときってありますよね。でも、同じプロパティ(特にtransform)を複数のアニメーションで操作すると、後から指定したほうに上書きされちゃうんですよね。

今回はそんな問題を解決してくれる animation-composition プロパティを試してみました。

サンプルページを見る(replace/add/accumulateの比較・回転+移動合成・パルス+バウンスのインタラクティブデモ)

複数アニメーションの上書き問題

たとえば、要素に「回転」と「移動」のアニメーションを同時にかけたいとします。こんな感じで書きますよね。

@keyframes rotate {
  to { transform: rotate(360deg); }
}

@keyframes move {
  to { transform: translateX(200px); }
}

.box {
  animation: rotate 2s linear infinite, move 2s ease-in-out infinite alternate;
}

これだと movetransformrotatetransform を上書きしてしまいます。結果として、回転せずに移動だけするという動きになっちゃうんですよね。

これがCSSアニメーションの「上書き問題」です。同じプロパティを複数の @keyframes で指定すると、後に書いたほうが勝ちます。

animation-composition とは

animation-composition は、複数のアニメーションが同じプロパティを操作するとき、それらをどう合成するかを制御するプロパティです。3つの値があります。

  • replace(デフォルト)
  • add
  • accumulate

それぞれ見ていきますね。

replace(デフォルト)

replace はデフォルトの挙動です。これは従来どおり、アニメーションの値が要素の基本値を完全に置き換えます。複数のアニメーションが同じプロパティを操作する場合、後に指定したものが勝ちます。

.box {
  animation-composition: replace; /* デフォルト */
}

つまり今までと同じ挙動ですね。上書き問題がそのまま起きます。

add(合成)

add は、アニメーションの効果を要素の基本値に「追加」します。transformの場合、変換関数がリストとして結合されます。

.box {
  transform: scale(1.5);
  animation: slide 2s ease-in-out infinite;
  animation-composition: add;
}

@keyframes slide {
  to { transform: translateX(100px); }
}

この場合、要素の基本の scale(1.5) に、アニメーションの translateX(100px) が追加されます。結果として scale(1.5) translateX(100px) のように合成されるイメージですね。

accumulate(値の加算)

accumulateadd と似ていますが、ちょっと違います。add が変換関数をリストとして結合するのに対して、accumulate は同じ種類の変換関数の値を数値的に加算します。

.box {
  transform: translateX(50px);
  animation: slide 2s ease-in-out infinite;
  animation-composition: accumulate;
}

@keyframes slide {
  to { transform: translateX(100px); }
}

この場合、基本値の translateX(50px) とアニメーションの translateX(100px) が数値的に加算されて、translateX(150px) になります。add だと translateX(50px) translateX(100px) と2つ並ぶのに対して、accumulate は1つにまとめてくれるんですよね。

実例1: 回転 + 移動を同時にかける

冒頭の問題を animation-composition: add で解決してみました。

@keyframes rotate {
  to { transform: rotate(360deg); }
}

@keyframes move {
  to { transform: translateX(200px); }
}

.box {
  width: 80px;
  height: 80px;
  background: #3b82f6;
  animation: rotate 2s linear infinite, move 2s ease-in-out infinite alternate;
  animation-composition: add;
}

animation-composition: add を指定することで、回転しながら移動するアニメーションが実現できました。上書きされずに、両方のtransformが合成されるのが確認できますね。

実例2: ホバー時に追加アニメーションを重ねる

常時ふわふわ浮遊しているボタンに、ホバーしたときだけ拡大アニメーションを追加する例を作ってみました。

@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}

@keyframes grow {
  to { transform: scale(1.2); }
}

.button {
  padding: 12px 24px;
  background: #8b5cf6;
  color: white;
  border: none;
  border-radius: 8px;
  animation: float 3s ease-in-out infinite;
  animation-composition: add;
}

.button:hover {
  animation: float 3s ease-in-out infinite, grow 0.3s ease forwards;
  animation-composition: add;
}

ホバーすると浮遊アニメーションを維持したまま、拡大アニメーションが追加されます。animation-composition: add がないと、ホバー時に grow のtransformが float のtransformを上書きしてしまいます。

実例3: パルス + バウンスの組み合わせ

通知バッジのような要素に、パルス(拡大縮小)とバウンス(跳ねる)を同時に適用してみました。

@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.3); }
}

@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-20px); }
}

.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: #ef4444;
  color: white;
  border-radius: 50%;
  font-weight: bold;
  animation: pulse 1s ease-in-out infinite, bounce 0.6s ease-in-out infinite;
  animation-composition: add;
}

これで拡大縮小しながら跳ねるバッジができました。目立たせたい通知表示なんかに使えそうですね。

add と accumulate の使い分け

addaccumulate の違いをまとめておきますね。

  • add: transform関数をリストとして結合する。rotate()translateX() のように異なる種類の変換を合成するときに向いている
  • accumulate: 同じ種類のtransform関数の値を数値的に加算する。translateX(50px)translateX(100px)translateX(150px) にしたいときに使う

基本的には add を使っておけば、多くのケースで意図どおりの合成ができると思います。

ブラウザ対応状況

2026年3月時点での animation-composition のブラウザ対応状況です。

  • Chrome: 112以降で対応
  • Edge: 112以降で対応
  • Firefox: 115以降で対応
  • Safari: 16.4以降で対応

主要ブラウザはすべて対応済みですね。安心して使える状況になっています。

まとめ

animation-composition を使うことで、CSSアニメーションのtransform上書き問題を解決できることがわかりました。

  • replace: デフォルト。従来どおりの上書き挙動
  • add: 変換関数をリストとして合成。異なる種類のtransformを組み合わせるのに便利
  • accumulate: 同種の変換関数の値を数値的に加算

複数のアニメーションを組み合わせたい場面って結構あるので、覚えておくと便利なプロパティですね。

サンプルページで実際の動きを確認する

今回は以上です!