# Use cases for transitions/animations/effects

Use case | Current drafts (transitions, animations) | the 'effect' proposal | Tab's proposal | Brad's proposal | Andrew's proposal [1], [2] | Use case
--- | --- | --- | --- | --- | --- | ---
1a: Change the color of an element from red to green when the element is hovered. The change should occur over a period of 1 second. When the element is un-hovered, the reverse change should occur. |
    foo {
      color: red;
      transition: color 1s;
    }
    foo:hover {
      color: green;
    }
    foo {
      color: red;
      effect: change(color) 1s;
    }
    foo:hover {
      color: green;
    }

    foo {
      color: red;
      transition: color 1s;
    }
    foo:hover {
      color: green;
    }
    foo {
      color: red;
      transition: color 1s;
    }
    foo:hover {
      color: green;
    }
    foo {
      color red;
      animate: color 1s;
    }
    foo:hover {
      color: green;
    }
| 1a: Change the color of an element from red to green when the element is hovered. The change should occur over a period of 1 second. When the element is un-hovered, the reverse change should occur.
1b: Same as 1a, but the reverse change should take 0.8 second. |
    foo {
      color: red;
      transition: color 1s;
    }
    foo:hover {
      color: green;
      transition: color 0.8s;
    }
    foo {
      color: red;
      effect: change(color) 1s;
    }
    foo:hover {
      color: green;
      effect: change(color) 0.8s;
    }
    foo {
      color: red;
      transition: color 1s;
    }
    foo:hover {
      color: green;
      transition: color .8s;
    }
    foo {
      color: red;
      transition: color 1s;
    }
    foo:hover {
      color: green;
      transition: color 0.8s;
    }
    foo {
      color: red;
      animate: color 1s;
    }
    foo:hover {
      color: green;
      animate: color 0.8s;
    }
| 1b: Same as 1a, but the reverse change should take 0.8 second.
2a: Play the 'bounce animation once for 1s when the element is hovered. |
    foo:hover {
      animation: bounce 1s;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    foo:hover {
      effect: play(bounce) 1s;
    }
    @animation bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    foo:hover {
      play-in: bounce 1s;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    foo:hover {
      animation: bounce 1s;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    foo:hover {
      animate-in: "bounce" top 1s once;
    }
    @profile "bounce"
      0% 0px,
      33% -20px,
      66% 20px,
      100% 0px;
| 2a: Play the 'bounce animation once for 1s when the element is hovered.
2b: Same as 2a, but also play the animation when the element is un-hovered. | not possible in CSS |
    foo:hover {
      effect: play(bounce) 1s,
        on-exit play(bounce) 1s;
    }

    @animation bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    foo:hover {
      play-in: bounce 1s;
      play-out: bounce 1s;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    foo {
      position:static;
      transition: position 1s / bounce 1s;
    }
    foo:hover { position:relative; }

    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    foo:hover {
      animate: "bounce" top 1s once;
    }
    @profile "bounce"
      0% 0px,
      33% -20px,
      66% 20px,
      100% 0px;
| 2b: Same as 2a, but also play the animation when the element is un-hovered.
2c: Same as 2b, but play the animation in reverse when un-hovered. | not possible |
    foo:hover {
      effect: play(bounce) 1s,
        on-exit play(bounce) 1s reverse;
    }
    @animation bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    foo:hover {
      play-in: bounce 1s;
      play-out: bounce reversed 1s;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
(or whatever, I don't care how keyframes are reversed, as long as they can be reversed) |
    foo {
      position:static;
      transition: position 1s / bounce 1s alternate;
    }
    foo:hover {
      position:relative;
      transition-animation: bounce 1s;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    foo:hover {
      animate-in:  "bounce" top 1s once;
      animate-out: "reversed-bounce" top 1s once;
    }
    @profile "reversed-bounce"
      0% 0px,
      33% 20px,
      66% -20px,
      100% 0px;

    @profile "bounce"
      0% 0px,
      33% -20px,
      66% 20px,
      100% 0px;
| 2c: Same as 2b, but play the animation in reverse when un-hovered.
3a: When an element's class changes from "one" to "two", move the element 500px rightwards and simultaneously play the 'bounce' animation 5 times for a total of 1s. |
    .one {
      position: relative;
      left: 0px;
      transition: left 1s;
    }
    .two {
      position: relative;
      left: 500px;
      animation: bounce 0.2s 5;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    .one {
      position: relative;
      left: 0px;
      effect: change(left) 1s;
    }
    .two {
      position: relative;
      left: 500px;
      effect: play(bounce) 0.2s 5;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    .one {
      position: relative;
      left: 0px;
      transition: left 1s;
    }
    .two {
      position: relative;
      left: 500px;
      play-in: bounce .2s 5;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    .one {
      position: relative;
      left: 0px;
      transition: left 1s;
    }
    .two {
      position: relative;
      left: 500px;
      animation: bounce 0.2s 5;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    .one {
      position: relative;
      left: 0px;
    }
    .two {
      position: relative;
      left: 500px;
      animate-in: "bounce" top 0.2s 5,
                  linear left 1s once;
    }
    @profile "bounce"
      0% 0px,
      33% -20px,
      66% 20px,
      100% 0px;
| 3a: When an element's class changes from "one" to "two", move the element 500px rightwards and simultaneously play the 'bounce' animation 5 times for a total of 1s.
3b: Same as 3a, but also play the 'bounce' animation when the class of the element is changed back from "two" to "one", while the element is moved back to its original position. | not possible in CSS |
    .one {
      position: relative;
      left: 0px;
      effect: change(left) 1s;
    }

    .two {
      position: relative;
      left: 500px;
      effect: play(bounce) 10 0.1s,
        on-exit play(bounce);
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    .one {
      position: relative;
      left: 0px;
      transition: left 1s play(bounce .2s 5);
    }

    .two {
      position: relative;
      left: 500px;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    .one {
      position: relative;
      left: 0px;
      transition: left 1s / bounce .2s 5;
    }
    .two {
      position: relative;
      left: 500px;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    .one {
      position: relative;
      left: 0px;
    }
    .two {
      position: relative;
      left: 500px;
      animate: "bounce" top 0.2s 5,
                 linear left 1s once;
    }
    @profile "bounce"
      0% 0px,
      33% -20px,
      66% 20px,
      100% 0px;
| 3b: Same as 3a, but also play the 'bounce' animation when the class of the element is changed back from "two" to "one", while the element is moved back to its original position.
3c: Same as 3b, but play the 'sway' animation (which takes 2s to run) continuously between the two 'bounce' animations. | not possible in CSS |
    .one {
      position: relative;
      left: 0px;
      change(left) 1s;
    }

    .two {
      position: relative;
      left: 500px;
      effect: play(bounce) 10 0.1s,
        play(sway) 2s 1s during,
        on-exit play(bounce);
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    @keyframes sway {
      from { left: 0; }
      33%  { left: -20px; }
      66%  { left: 20px; }
      to   { left: 0; }
    }
    .one {
      position: relative;
      left: 0px;
      transition: left 1s play(bounce .2s 5);
    }

    .two {
      position: relative;
      left: 500px;
      play-during: sway 1s 1s;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
(Delay added to make it wait until the transition is done.) |
    .one {
      position: relative;
      left: 0px;
      transition: left 1s / bounce .2s 5;
    }
    .two {
      position: relative;
      left: 500px;
      transition: left 1s / bounce .2s 5;
      animation: bounce 0.2s 5, sway 1s 1s infinite;
    }
    @keyframes bounce {
      from { top: 0; }
      33%  { top: -20px; }
      66%  { top: 20px; }
      to   { top: 0; }
    }
    .one {
      position: relative;
      left: 0px;
    }
    .two {
      position: relative;
      left: 500px;
      animate: "bounce" top 0.2s 5,
               linear left 1s once,
               "bounce" left 1s 1s infinite;
    }
    @profile "bounce"
      0% 0px,
      33% -20px,
      66% 20px,
      100% 0px;
| 3c: Same as 3b, but play the 'sway' animation (which takes 2s to run) continuously between the two 'bounce' animations.

## The 'effect' property

The 'effect' property accepts a comma-separated list of effects as value. Each effect must contain on change() or play() function in addition to optional other values. An effect is referred to as a 'change effect' or a 'play effect'.

The change() function takes a property name as value. A change effect indicates that the specified property should be monitored; whenever it changes, the change effect will be shown. The length of the change, the delay of the change, and the timing function of the change can be specified. For example, this declaration specifies that the change should take 1s, there should be a 0.2s delay for both changes, and the 'ease-in' timing function should be applied:

       effect: change(left) 1s 0.2s ease-in;

The play() function takes the name of an animation as value. Animations are specified in separate @animation constructs. Unlike change effects, play effects are not triggered by value changes other properties, but rather by value changes on the 'effect' property itself. When an element is assigned a new value on 'effect' property, the value is examined and any effects set to start immediately are started, while effects with delays are scheduled to be started later. Further, any effect marked to start 'on-exit' on the previous value is started. For example, this rule specifies that the 'bounce' animation should be played twice: when the 'effect' value is first set, and when the 'effect' value is reset the animation is played in reverse:

      a:hover {
        effect: play(bounce) 1s,
          on-exit play(bounce) 1s reverse;
      }

The 'on-exit' can be considered to be a delay equal to 0.

The 'reverse' keyword is offered as an alternative to the proposed 'alternate' keyword.

The 'during' keyword is offered as an alternative to the proposed 'infinite' keyword.

Otherwise, the values are the same as in the transitions, animations proposal.