w3c / w3c/csswg-drafts

[css-transitions] starting an animation and a transition with equal values yields some incompatible behavior between Safari, Chrome and Firefox

Open
#8,701 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

css-transitions-1
Dominant language
Bikeshed
Stars
4.9k
Forks
816
PR merge metrics
PR metrics pending

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:

  1. Chrome Canary (114.0.5708.0): no transition is ever started (no transitionstart event and no CSSTransition object visible when calling getAnimations() right after applying the animated class).
  2. Firefox Nightly (114.0a1 (2023-04-11)): a transition going from width: 0px to width: 1000px is started as the animated class is applied and runs for 400ms until its natural completion.
  3. Safari Technology Preview (167): same behavior as Firefox when the animated class 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the supplied HTML test and comparing transitionstart, transitioncancel, transitionend, CSSAnimation, and CSSTransition behavior in Chrome, Firefox, and Safari. Read the CSS transitions and animations specifications to determine the expected interaction; done means the behavior is specified clearly enough to resolve the browser differences.

Written by the indexing model from the issue text.

Assessment

Tech stack
css, html, javascript
Domain
frontend, web-dev
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.