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;
}これだと move の transform が rotate の transform を上書きしてしまいます。結果として、回転せずに移動だけするという動きになっちゃうんですよね。
これがCSSアニメーションの「上書き問題」です。同じプロパティを複数の @keyframes で指定すると、後に書いたほうが勝ちます。
animation-composition とは
animation-composition は、複数のアニメーションが同じプロパティを操作するとき、それらをどう合成するかを制御するプロパティです。3つの値があります。
replace(デフォルト)addaccumulate
それぞれ見ていきますね。
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(値の加算)
accumulate は add と似ていますが、ちょっと違います。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 の使い分け
add と accumulate の違いをまとめておきますね。
- 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: 同種の変換関数の値を数値的に加算
複数のアニメーションを組み合わせたい場面って結構あるので、覚えておくと便利なプロパティですね。
今回は以上です!