Skip to content

Commit b21dc41

Browse files
FF142 Animation.commitStyles() automatically fills values (mdn#40585)
* FF142 Animation.commitStyles() automatically fills values * Update files/en-us/web/api/animation/commitstyles/index.md Co-authored-by: wbamberg <will@bootbonnet.ca> * Apply suggestions from code review Co-authored-by: wbamberg <will@bootbonnet.ca> * Add reset button and comparision button with no styles saved * Update files/en-us/web/api/animation/commitstyles/index.md Co-authored-by: wbamberg <will@bootbonnet.ca> --------- Co-authored-by: wbamberg <will@bootbonnet.ca>
1 parent 4b3e451 commit b21dc41

File tree

1 file changed

+137
-19
lines changed
  • files/en-us/web/api/animation/commitstyles

1 file changed

+137
-19
lines changed

files/en-us/web/api/animation/commitstyles/index.md

Lines changed: 137 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@ browser-compat: api.Animation.commitStyles
88

99
{{APIRef("Web Animations")}}
1010

11-
The `commitStyles()` method of the [Web Animations API](/en-US/docs/Web/API/Web_Animations_API)'s {{domxref("Animation")}} interface writes the [computed values](/en-US/docs/Web/CSS/CSS_cascade/Value_processing#computed_value) of the animation's current styles into its target element's [`style`](/en-US/docs/Web/HTML/Reference/Global_attributes/style) attribute. `commitStyles()` works even if the animation has been [automatically removed](/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API#automatically_removing_filling_animations).
11+
The `commitStyles()` method of the [Web Animations API](/en-US/docs/Web/API/Web_Animations_API)'s {{domxref("Animation")}} interface writes the [computed values](/en-US/docs/Web/CSS/CSS_cascade/Value_processing#computed_value) of the animation's current styles into its target element's [`style`](/en-US/docs/Web/HTML/Reference/Global_attributes/style) attribute.
1212

13-
`commitStyles()` can be used in combination with `fill` to cause the final state of an animation to persist after the animation ends. The same effect could be achieved with `fill` alone, but [using indefinitely filling animations is discouraged](https://drafts.csswg.org/web-animations-1/#fill-behavior). Animations [take precedence over all static styles](/en-US/docs/Web/CSS/CSS_cascade/Cascade#cascading_order), so an indefinite filling animation can prevent the target element from ever being styled normally.
14-
15-
Using `commitStyles()` writes the styling state into the element's [`style`](/en-US/docs/Web/HTML/Reference/Global_attributes/style) attribute, where they can be modified and replaced as normal.
13+
It is primarily used to write the styles for the final state of an animation into the target element, so that the styling persists after the animation ends.
1614

1715
## Syntax
1816

@@ -28,68 +26,188 @@ None.
2826

2927
None ({{jsxref("undefined")}}).
3028

29+
## Description
30+
31+
The `commitStyles()` method is primarily used to write the [computed values](/en-US/docs/Web/CSS/CSS_cascade/Value_processing#computed_value) for the final state of an animation into the target element's [`style`](/en-US/docs/Web/HTML/Reference/Global_attributes/style) attribute, so that the styling persists after the animation ends.
32+
This can be done when the animation has finished (that is, the {{domxref("Animation")}} object's {{domxref("Animation.finished","finished")}} property has resolved).
33+
34+
### `commitStyles()` alongside fill mode
35+
36+
On older browsers, you must specify the [`fill` mode](/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#fill) in order to be able to commit the styles to the element _after_ the animation has finished.
37+
38+
The code below shows how you can animate an element named `animatedElement`, setting [`fill: "forwards"`](/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#fill) to persist the animation styles after it finishes.
39+
Once the animation is finished we commit the styles to the element with `commitStyles()`.
40+
41+
```js
42+
// Start the animation
43+
const animation = animatedElement.animate(
44+
{ transform: "translate(100px)" },
45+
{ duration: 500, fill: "forwards" },
46+
);
47+
48+
// Wait for the animation to finish
49+
await animation.finished;
50+
// Commit animation state to he animatedElement style attribute
51+
animation.commitStyles();
52+
// Cancel the animation
53+
animation.cancel();
54+
```
55+
56+
As `fill` persists the animation indefinitely, once we've committed the styles, we cancel the animation.
57+
58+
Note that the same effect could be achieved with `fill` alone, but [using indefinitely filling animations is discouraged](https://drafts.csswg.org/web-animations-1/#fill-behavior).
59+
Animations [take precedence over all static styles](/en-US/docs/Web/CSS/CSS_cascade/Cascade#cascading_order), so an indefinite filling animation can prevent the target element from ever being styled normally.
60+
61+
> [!NOTE]
62+
> You might also avoid having to explicitly save the final state by setting them as the element initial styles and animating to the final styles.
63+
64+
### `commitStyles()` without setting fill mode
65+
66+
In newer browsers you do not need to set the [`fill` mode](/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#fill) (see the [browser compatibility table](#browser_compatibility) for specific versions).
67+
68+
> [!NOTE]
69+
> There is no way to feature check for this new behaviour.
70+
> For now most code should continue to set `fill` as shown in the previous section.
71+
72+
The code below shows how you can animate an element named `animatedElement`, wait on the animation to complete using the {{domxref("Animation.finished","finished")}} property, and then commit the styles to the element with `commitStyles()`.
73+
Because we're not setting `fill` we don't have to cancel the animation afterwards.
74+
75+
```js
76+
// Start the animation
77+
const animation = animatedElement.animate(
78+
{ transform: "translate(100px)" },
79+
{ duration: 500 },
80+
);
81+
82+
// Wait for the animation to finish
83+
await animation.finished;
84+
85+
// Commit animation state to the animatedElement style attribute
86+
animation.commitStyles();
87+
```
88+
89+
`commitStyles()` works even if the animation has been [automatically removed](/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API#automatically_removing_filling_animations).
90+
After the element's styles have been committed they can be modified and replaced as normal.
91+
3192
## Examples
3293

33-
### Committing the final state of an animation
94+
### Animation with and without using fill
3495

35-
In this example we have two buttons, labeled "Commit styles" and "Fill forwards". Both buttons animate when you click them, and both buttons persist the final state of the animation.
96+
This example demonstrates how you can use `commitStyles()` to save the computed styles at the end of the animation, both with and without using `fill`.
97+
It also provides an example of what happens if neither `commitStyles()` or `fill` are used, for comparison.
3698

37-
The difference, though, is that "Fill forwards" only uses `fill: "forwards"` to persist the animation's final state: this means that the browser has to maintain the animation's state indefinitely, or until it can be automatically removed.
99+
The example first displays two buttons labelled "commitStyles() only" and "commitStyles() with fill".
100+
Both buttons animate when you click them, and both buttons call `commitStyles()` to persist the final state of the animation.
101+
The difference is that "commitStyles() only" does not specify `fill: "forwards"` to persist the animation's final state.
102+
On browsers that don't match the current specification the final state may not be captured.
38103

39-
However, the "Commit styles" button waits for the animation to finish, then calls `commitStyles()`, then cancels the animation, so the finished style is captured as the value of the `style` attribute, rather than as the animation state.
104+
The code then displays a button "No commitStyles() or fill" that can be used for comparison, and a "Reset" button.
40105

41106
#### HTML
42107

43108
```html
44-
<button class="commit-styles">Commit styles</button>
45-
<br />
46-
<button class="fill-forwards">Fill forwards</button>
109+
<button class="commit-styles">commitStyles() only</button>
110+
<button class="commit-with-fill">commitStyles() with fill</button>
111+
<button class="no-commit-or-fill">No commitStyles() or fill</button>
112+
```
113+
114+
```html hidden
115+
<button id="reset" type="button">Reset</button>
47116
```
48117

49118
```css hidden
50119
button {
51120
margin: 0.5rem;
121+
display: block;
52122
}
53123
```
54124

125+
```js hidden
126+
const reload = document.querySelector("#reset");
127+
128+
reload.addEventListener("click", () => {
129+
window.location.reload(true);
130+
});
131+
```
132+
55133
#### JavaScript
56134

135+
This code defines a click handler for the "commitStyles() only" button.
136+
This animates the button to move right or left when it is clicked.
137+
Note that `commitStyles()` is called immediately after the animation is finished.
138+
57139
```js
58-
const commitStyles = document.querySelector(".commit-styles");
59140
let offset1 = 0;
60141

142+
const commitStyles = document.querySelector(".commit-styles");
143+
61144
commitStyles.addEventListener("click", async (event) => {
62145
// Start the animation
63146
offset1 = 100 - offset1;
64147
const animation = commitStyles.animate(
65148
{ transform: `translate(${offset1}px)` },
66-
{ duration: 500, fill: "forwards" },
149+
{ duration: 500 },
67150
);
68151

69152
// Wait for the animation to finish
70153
await animation.finished;
71154
// Commit animation state to style attribute
72155
animation.commitStyles();
73-
// Cancel the animation
74-
animation.cancel();
75156
});
157+
```
158+
159+
This code defines a click handler for the "commitStyles() with fill" button.
160+
This also animates the button to move right or left when it is clicked.
161+
As it defines a `fill` it needs to cancel the animation afterwards.
76162

77-
const fillForwards = document.querySelector(".fill-forwards");
163+
Note that `commitStyles()` is called immediately after the animation is finished.
164+
165+
```js
166+
const commitStylesWithFill = document.querySelector(".commit-with-fill");
78167
let offset2 = 0;
79168

80-
fillForwards.addEventListener("click", async (event) => {
169+
commitStylesWithFill.addEventListener("click", async (event) => {
81170
// Start the animation
82171
offset2 = 100 - offset2;
83-
const animation = fillForwards.animate(
172+
const animation = commitStylesWithFill.animate(
84173
{ transform: `translate(${offset2}px)` },
85174
{ duration: 500, fill: "forwards" },
86175
);
176+
177+
// Wait for the animation to finish
178+
await animation.finished;
179+
// Commit animation state to style attribute
180+
animation.commitStyles();
181+
// Cancel the animation
182+
animation.cancel();
183+
});
184+
```
185+
186+
This code defines a click handler for the "No commitStyles() or fill" button.
187+
This also animates the button to move right or left when it is clicked.
188+
It doesn't define a fill and we don't cancel the animation.
189+
190+
```js
191+
const noCommitStylesOrFill = document.querySelector(".no-commit-or-fill");
192+
let offset3 = 0;
193+
194+
noCommitStylesOrFill.addEventListener("click", async (event) => {
195+
// Start the animation
196+
offset3 = 100 - offset3;
197+
const animation = noCommitStylesOrFill.animate(
198+
{ transform: `translate(${offset3}px)` },
199+
{ duration: 500 },
200+
);
87201
});
88202
```
89203

90204
#### Result
91205

92-
{{EmbedLiveSample("committing_the_final_state_of_an_animation")}}
206+
Click the buttons to animate them.
207+
Note that the first button will "jump" at the end of the animation if the current browser still requires `fill` for styles to be committed after the end of the animation.
208+
The "No commitStyles() or fill" button always jumps at the end, because the final state is not saved.
209+
210+
{{EmbedLiveSample("Animation with and without using fill")}}
93211

94212
## Specifications
95213

0 commit comments

Comments
 (0)