animation-composition CSS propertyThe animation-composition CSS property specifies the composite operation to use when multiple animations affect the same property simultaneously.
/* Single animation */
animation-composition: replace;
animation-composition: add;
animation-composition: accumulate;
/* Multiple animations */
animation-composition: replace, add;
animation-composition: add, accumulate;
animation-composition: replace, add, accumulate;
/* Global values */
animation-composition: inherit;
animation-composition: initial;
animation-composition: revert;
animation-composition: revert-layer;
animation-composition: unset;This property is specified as one or more comma-separated keyword values:
replaceThe effect value overrides the underlying value of the property. This is the default value.
addThe effect value builds on the underlying value of the property. This operation produces an additive effect. For animation types where the addition operation is not commutative, the order of the operands is the underlying value followed by the effect value.
accumulateThe effect and underlying values are combined. For animation types where the addition operation is not commutative, the order of the operands is the underlying value followed by the effect value.
Each property that is targeted by the @keyframes at-rule is associated with an effect stack. The value of the effect stack is calculated by combining the underlying value of a property in a CSS style rule with the effect value of that property in the keyframe. The animation-composition property helps to specify how to combine the underlying value with the effect value.
For example, in the CSS below, blur(5px) is the underlying value, and blur(10px) is the effect value. The animation-composition property specifies the operation to perform to produce the final effect value after compositing the effect of the underlying value and the effect value.
.icon:hover {
filter: blur(5px);
animation: 3s infinite pulse;
animation-composition: add;
}
@keyframes pulse {
0% {
filter: blur(10px);
}
100% {
filter: blur(20px);
}
}Consider different values for the animation-composition property in the above example. The final effect value in each of those cases will be calculated as explained below:
replace, blur(10px) will replace blur(5px) in the 0% keyframe. This is the default behavior of the property.add, the composite effect value in the 0% keyframe will be blur(5px) blur(10px).accumulate, the composite effect value in 0% keyframe will be blur(15px).Note: A composite operation can also be specified in a keyframe. In that case, the specified composite operation is used for each property first within that keyframe and then on each property in the next keyframe.
When you specify multiple comma-separated values on an animation-* property, they will be applied to the animations in the order in which the animation-names appear. If the number of animations and compositions differ, the values listed in the animation-composition property will cycle from the first to the last animation-name, looping until all the animations have an assigned animation-composition value. For more information, see Setting multiple animation property values.
| Initial value | replace |
|---|---|
| Applies to | all elements |
| Inherited | no |
| Computed value | as specified |
| Animation type | Not animatable |
animation-composition =
<single-animation-composition>#
<single-animation-composition> =
replace |
add |
accumulate
The example below shows the effect of different animation-composition values side-by-side.
<div class="container">
replace
<div id="replace" class="target"></div>
</div>
<div class="container">
add
<div id="add" class="target"></div>
</div>
<div class="container">
accumulate
<div id="accumulate" class="target"></div>
</div>@keyframes slide {
50% {
transform: translateY(30px);
}
100% {
transform: translateX(150px);
}
}
.target {
transform: translateX(30px) rotate(45deg);
animation: slide 5s linear infinite;
}
#replace {
animation-composition: replace;
}
#add {
animation-composition: add;
}
#accumulate {
animation-composition: accumulate;
}The underlying value for the transform property in all cases is translateX(30px) rotate(45deg). The different animation-composition values' effects are as follows:
With replace, the transform property in each keyframe entirely replaces the underlying transform property set on the animated element. The final effect value for the transform property at the 50% keyframe is translateY(30px) (no rotate or translateX); at the 100% keyframe, it is translateX(150px) (no rotate or translateY).
The target starts at transform: translateX(30px) rotate(45deg) and effectively animates to transform: translateY(30px), then to transform: translateX(150px).
With add, the final effect value at each keyframe is the underlying transform value with the effect value placed immediately after it.
Therefore, the target starts at transform: translateX(30px) rotate(45deg) and effectively animates first to transform: translateX(30px) rotate(45deg) translateY(30px) (which is 30px "downwards" on the rotated Y-axis), and then to transform: translateX(30px) rotate(45deg) translateX(150px). Since the additive operation is relative to the underlying transform and not the previous keyframe, there is no translateY(30px) at 100%, placing the element 150px along the rotated X-axis from the original position.
With accumulate, the final effect value is the keyframe's effect transform combined with the underlying original. At 50%, translateY(30px) combines with the original translateX(30px) into a single translation (translate(30px, 30px)). At 100%, the translateX(150px) combines with the original translateX(30px) to create translateX(180px).
Therefore, the target starts at transform: translateX(30px) rotate(45deg) and effectively animates first to transform: translate(30px, 30px) rotate(45deg), and then to transform: translateX(180px) rotate(45deg).