Animations & Transitions

rvsp.github.io/CSS/animations/

Animations & Transitions

Transitions

  • Transitions overview
  • Transitions Properties
  • transition
  • transition-property
  • transition-duration
  • transition-timing-function
  • transition-delay
  • Animatable Properties
  • Tips and Events

Animations

  • Overview
  • Animation Essentials
  • @Keyframes
    • Naming
    • Keyframes
    • Declaration Lists
  • Animation properties
    • animation-name
    • animation-duration
    • animation-timing-function
    • Steps and bezier curves
    • animation-iteration-count
    • animation-delay
    • animation-direction
    • animation shorthand
    • animation-fill-mode
    • animation-play-state
  • Developer Tools
  • Animation Events

Transitions

Simplest Transition

a {
  color: green;
}
a:hover {
  color: orange;
}

Hover Over Me

CSS Transition

a {
  color: green;
  transition: 1s;
}
a:hover {
  color: orange;
}

Hover Over Me

Transitions Properties

Transitions Properties

Pprovide a way to control the animation when changing CSS property values. Instead of instaneous changes from one value to the next, the value can transition over a period of time, following an acceleration curve, the start of which can be delayed.

  • transition-property: properties that transition
  • transition-duration: time it takes to transition
  • transition-timing-function: bezier curve or steps of transition
  • transition-delay: time delay before transition starts
  • transition: shorthand for the four transition properties

These enable customization of the delay, timing, and duration of the transition between the two values of the property that is being changed.

transition property

Shorthand property for transition-property, transition-duration, transition-timing-function, and transition-delay.

 none | [ <property> ] || <duration> || <timing-function> || <delay> ]#

One or more single-property transitions, separated by commas.

li ul:hover {
     transition: transform 200ms ease-in 50ms,
                 color 50ms linear;
  }

Transition between two states of an element, like default and :hover or :invalid, or between a JS toggling of a class name.

transition-property property

CSS properties to which a transition effect should be applied

none | all | <custom-ident>#

Either none, or all and / or a comma-separated list

none
No properties will transition.
all
All properties that can transition will.
<custom-ident>
The comma-separated properties to which a transition effect should be applied
transition-duration: transform, color;

If using all with other properties, define all first.

If a property is the list is invalid, but the syntax is correct, the property will be kept in the list so other properties align correctly

transition-duration property

Sets the length of time a transition animation should take to complete.

<time>#
<time>
In s for seconds or ms for milliseconds, set the amount of time the transition will take to go from the old value of a property to the new value should take, after it starts. A time of 0s indicates that no transition will happen, that is the switch between the two states will be instantaneous. Negative values are invalid.
transition-duration: 200ms, 50ms;

Each duration is applied to the corresponding property as specified by the transition-property property. If there are fewer durations than properties the duration list is repeated. Too many is OK too.

transition-timing-function property

Provide an acceleration curve to control the speed of the transition over its duration.

linear | ease | ease-in | ease-out | ease-in-out | start | end
cubic-bezier( n1, n2, n3, n4 ) | step-start | step-end  
steps(<int>, <pos>) | jump-start | jump-end | jump-none | jump-both 

These will be described in huge detail in the animation section

transition-timing-function: ease-in, linear;

Each timing function is applied to the corresponding property as specified by the transition-property property. If there are fewer timing functions than properties the timing function list is repeated.

transition-delay property

Specifies the time to wait before starting a property's transition effect when its value changes.

<time>#

Specifies the amount of time to wait between a property's value changing and the start of the transition effect.

  • The value can be negative.
  • If negative the transition starts part of the way thru the transition.
  • There will be no visible transition if the delay is longer than the duration.
transition-duration: 50ms, 0ms;

Each delay is applied to the corresponding property as specified by the transition-property property. If there are fewer delays than properties, the delay list is repeated.

transitions

code {
   color: black;
   font-size: 85%;
   background-color: rgba(255,255,255,0.9);
   transition: all 2s ease-in 50ms;
}
code:hover {
   color: red;
   font-size: 120%;
   background-color: rgba(255,255,255,0.8);
}
code {
   transition:
      color, font-size, background-color 2s ease-in 50ms;
}

transitions

code {
   color: black;
   font-size: 85%;
   background-color: rgba(255,255,255,0.9);
   transition: all 2s ease-in 50ms;
}
code:hover {
   color: red;
   transform: scale(1.4);
   transform-origin: 0 0;
   background-color: rgba(255,255,255,0.8);
}
code {
   transition: transform 2s ease-in 50ms;
}

Animatable Properties

What can be transitioned?

Anything that has intermediate values

code {
  opacity: 1;
}
code:halfway {
  opacity: 0.5;
}
code:hover {
  opacity: 0;
}
code {
  display: block;
}
code:halfway {
  display: ???
}
code:hover {
  display: none;
}

What can be transitioned?

2 values that have REAL intermediary values

code {
  font-size: 100%;
}
code:halfway {
  font-size: 110%;
}
code:hover {
  font-size: 120%;
}
code {
  height: auto;
}
code:halfway {
  height: ???
}
code:hover {
  height: 1000px;
}

Transitionable Properties

all backdrop-filter background-color background-position background-size border-color border-radius border-width bottom box-shadow caret-color clip clip-path color column-count column-gap column-rule-color column-rule-width column-width filter flex-basis flex-grow flex-shrink font-size font-size-adjust font-stretch font-variation-settings font-weight gap grid-column-gap grid-gap grid-row-gap grid-template-columns grid-template-rows height inset inset-block inset-block-end inset-block-start inset-inline inset-inline-end inset-inline-start left letter-spacing line-clamp line-height margin mask mask-border mask-position mask-size max-height max-lines max-width min-height min-width object-position offset-anchor offset-distance offset-path offset-position offset-rotate opacity order outline-color outline-offset outline-width padding perspective perspective-origin right rotate row-gap scale scroll-margin scroll-padding scroll-snap-coordinate scroll-snap-destination scrollbar-color shape-image-threshold shape-margin shape-outside tab-size text-decoration-color text-emphasis-color text-indent text-shadow top transform transform-origin translate vertical-align visibility width word-spacing z-index zoom

Notes

Transition Features (or Limitations)

  • Single Iteration
  • Reverse goes to initial state
  • No granular control
  • Limited methods of initiation
  • Can't force them to finish

Tips

If a property is the list is invalid, but the syntax is correct, the property will be kept in the list so other properties align correctly.

Use transition-delay to chain transitions

The order is important: The duration must come before the delay!

Avoid transitioning to auto

Discrete

visibility
<input type=number min=0 max=10 step=2>

Events

transitionend event

  • Event thrown only when transition completes
  • transitionend for EVERY property
  • transitionend for each long-hand property within a shorthand
table {
  border: 1px black solid;
  transition: border 1s linear 50ms;
}
table:hover {
  border: 5px red solid;
}
  • border-top-color
  • border-right-color
  • border-bottom-color
  • border-left-color
  • border-top-width
  • border-right-width
  • border-bottom-width
  • border-left-width

Examples

Putting it together in the Real World

nav ul li {
  list-style-type: none;
}
nav > ul > li {
  display: inline-block;
  position:relative;
}
nav ul ul {
  transform: scale(1,0);
  transform-origin: top center;
  transition:0.2s linear 50ms;
  position:absolute;
  top: 100%;
}
nav li:hover ul {
  transform: scale(1,1);
}

Exercise

Pick a card

.card {
  position: absolute;
  perspective: 600px;
}
.card:hover {
  transition: 1s ease;
}
.card .front {
  transform: rotateX(0deg) rotateY(0deg);
  transform-style: preserve-3d;
  backface-visibility: hidden;
  transition: all .4s ease-in-out;
}
.card:hover .front {
  transform: rotateY(180deg);
}
.card .back {
  transform: rotateY(-180deg);
  transform-style: preserve-3d;
  backface-visibility: hidden;
  transition: all .4s ease-in-out;
}
.card:hover .back {
  transform: rotateY(0);
}
.card:first-of-type {
  transform: rotate(-5deg);
}
.card:nth-of-type(2):hover {
  transform: rotate(0) translatex(120px);
}
.card:last-of-type {
  transform: rotate(5deg);
}
.card:first-of-type:hover {
  transform: rotate(10deg) translatey(180px);
}

Animations

Animation Features (or limitations)

  • Single, many or infinite iterations
  • Single or bi-directional
  • Granular control
  • Can be initiated on page load
  • Has more robust JS Hooks
  • Can be paused
  • Lowest priority in UI Thread

Animation Essentials

  • @keyframes
  • animation-name
  • animation-duration
  • animation-timing-function
  • animation-iteration-count
  • animation-direction
  • animation-play-state
  • animation-delay
  • animation-fill-mode
  • animation (shorthand)

Keyframes

@keyframes at-rule

An at-rule that controls the intermediate steps in a CSS animation sequence by defining styles for keyframes along the animation sequence.

@keyframes <name> {
  [ <keyframe-selector># {
    <property-value-list>
  }]#
}

JavaScript can access via the CSSKeyframesRule interface.

Provides more control over transitions: alllow for intermediate steps

@Keyframes

@keyframes ...

Name your keyframe animation

@keyframes clever_name_here ...
  • Identifier or string
  • Unquoted Can now be!
  • If unquoted:
    • Characters [a-zA-Z0-9], -, _ and ISO 10646 characters U+00A0 and higher
    • ISO 10646 = Universal Character Set = Unicode standard
    • [-_a-zA-Z0-9\u00A0-\u10FFFF]
    • Can't start [0-9], -- , or hyphen+digit
    • Can contain escaped:
      Q&A! may be written as Q\&A\! or Q\26 A\21
  • Avoid using CSS property names or keyword values
  • Each animation should have a different name!

What's in a name?

Identifier: unquoted characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_). Try name, paused, Q&A!, Q\&A\!, Q\26 A\21 and ✎

at-rule

@keyframes slides {

}

Keyframe Selectors

Keyframe Selectors

Specifies percentages along the animation when the keyframe occurs.

[ from | to | <percentage> ]
from
0%
to
100%
<percentage>
A percentage of the time through the animation sequence at which the specified keyframe should occur.
  • Multiple percentage values for a keyframe block are separated by commas
  • They don't have to be in ascending order, but it helps make it more readable
  • Cascades like the rest of CSS

Keyframes

@keyframes writing {
    from {
      left: 0;
    }
    to {
      left: 100%;
    }
}

Keyframes

@keyframes writing {
    0% {
      left: 0;
    }

    100% {
      left: 100%;
    }
}

Don't forget the %

Quote on the animation name are optional in most cases

No 0% or 100%

@keyframes no0or100 {
  0% { background-color: red; border-width: 1px;}
  45% { background-color: green; border-width: 10px; }
  55% { background-color: blue;  border-width: 20px;}
  100% { background-color: red; border-width: 1px;}
}

Granular animation control

@keyframes writingWhileTired {
    0% {
      left: 0;
    }
    10% {
      left: 45%;
    }
    90% {
      left: 55%;
    }
    100% {
      left: 100%;
    }
}

Duplicate Keyframes?

@keyframes duplicate {
  45% { background-color: green; 
        opacity: .5; }
  55% { background-color: blue; 
        opacity: .7; }
  }

Properties

Declarating List

Every keyframe selector list has an associated <property-value-list>, better known as the declaration list

@keyframes 'myUniqueAnimation' {
  from {        /* 0% property: values */
    opacity: 1.0; color: red;     
  }
  25%, 75% {    /* values for both the 25 and 75% keyframe */
    opacity: 0.5; color: blue;
  }
  75% {         /* values unique to 75% */
    color: green;   /* overrides the blue */              
  }
  to {          /* 100% property: values */
    opacity: 0.9; color: orange;  
  }
}

Animating multiple properties

@keyframes W {
    0% {
      left: 0;
      top: 0;
    }
    25%, 75% {
      top: 400px;
    }
    50% {
      top: 50px;
    }
    100% {
      left: 80%;
      top: 0;
    }
}

Animating CSS Transforms

@keyframes gettingThePencil {
  0%{
    transform:
      translate3d(0, 0, 0)
      rotate(0deg)
      scale(0.5, 0.5);
  }

  100% {
    transform:
      translate3d(600px, 400px, 0)
      rotate(80deg)
      scale(1.2, 1.2);
  }
}

!important it isn't

 @keyframes important {
  0% { background-color: red;}
  45% { background-color: green; }
  100% { background-color: red;}
}

But nothing is
animated yet!

Base CSS

.pencil {
    width:100px;
    text-align: right;
    border-bottom: 10px solid;
}
.pencil::after {
  	content: '✎';
  	position: absolute;
  	bottom: -20px;
  	right: -10px;
}
@keyframes drawALine {
  0%{
    width:0;
    color:green;
  }
  100% {
    width: 100%;
    color:blue;
  }
}

Minimum requirements:
name and duration

animation-name property

Sets one or more animations to apply to an element.

[ none | <keyframes-name> ]#

Each name is an @keyframes at-rule that sets the property values for the animation sequence.

animation-name: red, blue, green, green, green;}
  • You can set the same animation on an element more than once
  • Comma separate the animation names
  • If "none" or no animation name is set, there will be no animation
  • You can quote the names, but if it is a valid <ident>, you don't have to.

animation-duration property

Sets the length of time that an animation takes to complete one cycle.

<time>#

A comma separated list of times in seconds (s) or milliseconds (ms).

animation-duration: 200ms, 300ms, 2s, 200ms, 200ms;

If there are more animation names than durations, the list will repeat. If there are more durations than animation, the extra durations will be ignored.

Negative values are ignored.

You must include the unit, even if the value is zero.

animation-name and animation-duration

.pencil { 
   animation-name: drawALine;
animation-duration: 3s;
  }

Order of Precedence

Whichever animation happens last is the background-color I will permanently be

Specificity

Based on important, I should be the same color as the header. Based on ID I should be blue. Based on animation, green.

Some browsers override erroneously override !important. This is against the specification

Based on the spec I should be the !important color from the non-animated state. If no important is set, I should be the animation's color.

animation-timing-function

animation-timing-function property

Sets how the animation progresses through the duration of a full animation iteration.

linear | ease | ease-in | ease-out | ease-in-out | start | end
cubic-bezier( n1, n2, n3, n4 ) | step-start | step-end  
steps(<int>, <pos>) | jump-start | jump-end | jump-none | jump-both 

The non-step keyword values are actually cubic Bézier curves with predefined four point values. Use the cubic-bezier() function for non-predefined values.

The step timing functions divide the input time into a specified number of intervals that are equal in length, with a number of steps and a step position.

animation-timing-function: ease-in, linear;

Each timing function is applied to the corresponding animation as specified by the animation-name property. If there are fewer timing functions than animations the timing function list is repeated.

animation-timing-function bezier curves

ease
Equal to cubic-bezier(0.25, 0.1, 0.25, 1.0), the default value, increases in velocity towards the middle of the animation, slowing back down at the end.
linear
Equal to cubic-bezier(0.0, 0.0, 1.0, 1.0), animates at an even speed.
ease-in
Equal to cubic-bezier(0.42, 0, 1.0, 1.0), starts off slowly, with the speed of the transition of the animating properting increasing until complete.
ease-out
Equal to cubic-bezier(0, 0, 0.58, 1.0), starts quickly, slowing down the animation continues.
ease-in-out
Equal to cubic-bezier(0.42, 0, 0.58, 1.0), with the animating properties slowly transitioning, speeding up, and then slowing down again.
cubic-bezier(p1, p2, p3, p4)
An author defined cubic-bezier curve, where the p1 and p3 values must be in the range of 0 to 1.

animation-timing-function non-bezier values

steps(n, <jumpterm>)
Displays an animation iteration along n stops along the transition, displaying each stop for equal lengths of time. For example, if n is 5, there are 5 steps. Whether the animation holds temporarily at 0%, 20%, 40%, 60% and 80%, on the 20%, 40%, 60%, 80% and 100%, or makes 5 stops between the 0% and 100% along the animation, or makes 5 stops including the 0% and 100% marks (on the 0%, 25%, 50%, 75%, and 100%) depends on which of the following jump terms is used:
jump-start
Denotes a left-continuous function, so that the first jump happens when the animation begins;
jump-end
Denotes a right-continuous function, so that the last jump happens when the animation ends;
jump-none
There is no jump on either end. Instead, holding at both the 0% mark and the 100% mark, each for 1/n of the duration.
jump-both
Includes pauses at both the 0% and 100% marks, effectively adding a step during the animation iteration.
start
Same as jump-start.
end
Same as jump-end.
step-start
Equal to steps(1, jump-start)
step-end
Equal to steps(1, jump-end)

‘animation-timing-function’

.pencil { 
  animation-name: drawALine;
  animation-duration: 5s;
  animation-timing-function: ease-in-out;
}
ease           linear
ease-in        ease-out
ease-in-out    cubic-bezier(x1, y1, x2, y2)
step-start /* same as steps(1, start) */
step-end /* same as steps(1, end) */
steps( X, start|end) /* X = # of steps + when change of value occurs */

Cubic Bezier

Try it out!

Cubic Bezier

Try it out!

Steps()

Try it out!

Steps()

Try it out!

steps(4, end)

  • 0%
  • 25%
  • 50%
  • 75%
  • 100%

Steps(4, end)

Try it out!

animation-iteration-count

animation-iteration-count property

Sets the number of times an animation cycle should be played before ending the animation.

[ infinite | <number> ]#

A comma-seperated list of interations, where the value is infinite or a number greater than or equal to zero. Doesn't need to be an interger.

infinite
Animation repeats forever
<number>
Default is 1. The number of times the animation will repeat. Non-integers mean "play part of an animation cycle. 1.5 will play the animation one and a half times (unless the delay is negative). Negative values are not valid.
animation-iteration-count: infinite, 3, 3, 1, 1, 1;

Each entry is matched up with an animation name. If there are too few, the list repeats, if there are too many, the last ones are ignored.

If 0, the animation still happens. Goes directly to the end.

‘animation-iteration-count’

.pencil {
  ...
  animation-name: drawALine;
  animation-duration: 3s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: 3;
}

‘infinite’ or number. Default is ‘1’.

Partial Iteration?

Try it out!

No Iteration?

Try it out!

animation-delay

animation-delay property

Sets when an animation starts. The animation can start immediately from its beginning or midway thru, or it can wait until a timer expires before starting from the beginning.

<time>#

A comma-seperated list of times, where each time is matched with an animation name. If there aren't enough delays listed, the list repeats. Extra are ignored

animation-delay: 0, 0, 0, 200ms, 2500ms, 5000ms;
  • The delay clock starts counting down when the animation is applied to the element.
  • The unit is required; specified in seconds (s) or milliseconds (ms).
  • The default is 0, meaning the animation should start immediately.
  • Negative values cause the animation to begin immediately, partway through an iteration. If an animation is 4second, occurs 3 times, if the delay is -6s, the animation will start immediately, half way thru the second iteration.
  • A positive value indicates that the animation should begin after the specified amount of time has elapsed.
  • If the delays have elapsed before the page has finished loading, while the main thread is occupied, the animations will start when they can.

‘animation-delay’

.pencil { 
  animation-name: drawALine;
  animation-duration: 8s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: 2;
  animation-delay: 2s;
}

animation-direction

animation-direction property

Sets whether an animation should play forwards, backwards, or alternating back and forth.

normal | reverse | alternate | alternate-reverse
normal
The animation plays forwards each cycle. In other words, each time the animation cycles, the animation will reset to the beginning state and start over again. This is the default value.
reverse
The animation plays backwards each cycle. In other words, each time the animation cycles, the animation will reset to the end state and start over again. Animation steps are performed backwards, and timing functions are also reversed. For example, an ease-in timing function becomes ease-out.
alternate
The animation reverses direction each cycle, with the first iteration being played forwards. The count to determine if a cycle is even or odd starts at one.
alternate-reverse
The animation reverses direction each cycle, with the first iteration being played backwards. The count to determinate if a cycle is even or odd starts at one.

‘animation-direction’

.pencil {
  ...
  animation-name: drawALine;
  animation-duration: 5s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: 5;
  animation-direction: normal
}

values: normal | alternate | reverse | alternate-reverse;

animation-direction: alternate;

animation shorthand

animation shorthand property

Shorthand for animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, animation-fill-mode, and animation-play-state. Well cover teh last two in a few minutes.

<time-duration> <timing-function> <time-delay> <iteration-count> 
    <direction> <fill-mode> <play-state> <keyframes-name> | none

A comma separated list of any or all those values.

animation: 200ms ease-in 100ms alternate infinite red,
           300ms linear 2s reverse 3 blue;

Order of properties matters to some extent:

  • ALWAYS put the duration before the delay.
  • First time a value makes sense as a longhand value, it will be used, so good idea to put the animation-name value last.
  • If you omit values, they default.

‘animation’ (shorthand)

.pencil {
  animation-name: drawALine;
  animation-duration: 5s;
  animation-delay: 100ms;
  animation-timing-function: ease-in-out;
  animation-iteration-count: 5;
  animation-direction: normal;
}

. . . can also be written as . . .

.pencil {
  animation: drawALine 5s ease-in-out 100ms 5;
}

Pick a card

.carda.flipped .front,
.carda.unflipped .back {
  animation: flipme 1s linear forwards;
}
.carda.unflipped .front,
.carda.flipped .back {
  animation: unflipme 1s linear both;
}
.card.flipped:nth-of-type(2){
  transform:
    rotate(0)
    translatex(120px);
}
.carda.flipped:first-of-type{
  transform:
    rotate(-5deg)
    translate(240px, 25px);
}
@keyframes flipme {
  0% {transform: rotatey(0deg)}
  100% {transform: rotateY(-180deg);}
}
@keyframes unflipme {
  0% {transform: rotatey(180deg)}
  100% {transform: rotateY(0deg);}
}

Before and After

animation-fill-mode property

Sets how a CSS animation applies the keyframe styles to the animated element before the animation starts and after it ends.

none | forwards | backwards | both #
none
Default. No keyframe styles are applied while the animation is not executing. The element will instead be displayed using any other CSS rules applied to it.
forwards
The computed values at the keyframe when the animation ended is maintained. The relevant keyframe depends on the value of animation-direction and animation-iteration-count
backwards
The properties as defined in the 0% keyframe in the case of animation-direction: normal or alternate and the properties defined in the 100% keyframe in the case of animation-direction: reverse or alternate-reverse will be applied from the moment the animation is applied to an element until the delay expires an the animation starts iterating.
both
both forwards and backwards are applied

‘animation-fill-mode’

values: none | forwards | backwards | both
.pencil {
  animation: gettingThePencil 3s ease-in-out 1s  forwards;
}
.pencil {
 animation-fill-mode: forwards;
  animation-name: gettingThePencil;
  animation-duration: 3s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: 1;
  animation-delay: 2s;
}

Animation Fill Mode (again)

animation-fill-mode: none;
animation-fill-mode: forwards;
animation-fill-mode: backwards;
animation-fill-mode: both;
.box { animation: showme 5s linear 5s 1;}
@keyframes showme {
	0% {left: 200px; background-color:blue;}
	50% {background-color:green;}
	100% {left: 600px; background-color: yellow;}
}

Test page

Animation Fill Mode

Try it out!

animation-play-state

Can you stop an animation?

animation-play-state property

Sets whether an animation is running or paused.

running | paused #

Resuming a paused animation will start the animation from where it left off at the time it was paused, rather than starting over from the beginning of the animation sequence.

animation-play-state: play, play, pause;
running
The animation is currently playing.
paused
The animation is currently paused.

While paused, the delay does not count down

‘animation-play-state’

animation-play-state: paused | running
.pencil {
	transform-origin: center 300px;
	animation: writingInCircles 3s linear infinite;
 }
.pencil:hover {
	animation-play-state:paused;
 }
@keyframes writingInCircles {
  100% {
    transform:
      rotate(360deg);
  }
}

‘animation-play-state’

animation-play-state: paused | running
.pencil:hover {
  animation-play-state: paused;
  }

Developer Tools

Check out the animation inspector

Events

What happens at animation end?

  • animationstart
  • animationend
  • animationiteration
el.addEventListener( 'animationend',
    function( event ) {
        console.log('Animation Ended');
    }, false );

Starting next animation at end of previous

el.addEventListener( 'animationend',
    function( event ) {
        el.removeClassName('newClass');
        setTimeout("el.addClassName('newClass')", 100ms)
    },
    false );
animationend

Events: start, lots 'o iterations, end

Try it out!

Other Stuff

Next ➹

Links