-
Notifications
You must be signed in to change notification settings - Fork 756
Description
If I have an element specified as follows:
div {
width: 0;
height: 100px;
background-color: black;
transition: width 250ms linear;
}… and later on set the following styles:
div.animated {
width: 1000px;
animation: grow 1s forwards linear;
}
@keyframes grow {
from { width: 0 }
to { width: 1000px }
}… then what is the expected behavior with regards to transition during the lifetime of the explicit CSS Animation started when the animated class is applied? I'm observing a different behavior in each of Chrome Canary, Firefox Nightly and Safari Technology Preview. In all three browsers a CSSAnimation is yielded going from width: 0px to width: 1000px as expected. However, the behavior differs greatly for the transition:
- Chrome Canary (114.0.5708.0): no transition is ever started (no
transitionstartevent and noCSSTransitionobject visible when callinggetAnimations()right after applying theanimatedclass). - Firefox Nightly (114.0a1 (2023-04-11)): a transition going from
width: 0pxtowidth: 1000pxis started as theanimatedclass is applied and runs for 400ms until its natural completion. - Safari Technology Preview (167): same behavior as Firefox when the
animatedclass is applied, however the transition is canceled and restarted on each frame.
While this does not yield a visible difference because the CSS Animation overrides the CSS Transition, this is still an observable difference through events and getAnimations().
Here's the complete test (sadly GitHub does not allow attaching an HTML file):
<!DOCTYPE html>
<style>
div {
width: 0;
height: 100px;
background-color: black;
transition: width 250ms linear;
}
div.animated {
width: 1000px;
animation: grow 1s forwards linear;
}
@keyframes grow {
from { width: 0 }
to { width: 1000px }
}
</style>
<div></div>
<script>
const div = document.querySelector("div");
const currentWidth = () => getComputedStyle(div).width;
const dumpAnimations = label => {
const animations = document.getAnimations().map(animation => {
const keyframes = animation.effect.getKeyframes();
return `${animation.constructor.name} from ${keyframes[0].width} to ${keyframes[1].width}`;
});
console.log(`${label} width is ${currentWidth()} and getAnimations() yields [${animations.join(', ')}]`);
}
const dumpTransitionEvent = event => dumpAnimations(`After ${event.type} fired`);
div.addEventListener("transitionstart", dumpTransitionEvent);
div.addEventListener("transitioncancel", dumpTransitionEvent);
div.addEventListener("transitionend", dumpTransitionEvent);
requestAnimationFrame(() => {
div.classList.add("animated");
dumpAnimations("After starting animations");
requestAnimationFrame(() => dumpAnimations("One frame after starting animations"));
setTimeout(() => dumpAnimations("100ms after starting animations"), 100);
setTimeout(() => dumpAnimations("500ms after starting animations"), 500);
});
</script>Cc people I know to have worked or are working on animations in the affected browsers: @flackr, @BorisChiou and @birtles.