Before we get into transitions vs animations, let us first discuss timing, which is a concept needed for both. Timing is the measure of how animation progress changes throughout a given interval. Animation timing in CSS is done using the cubic-bezier function:
cubic-bezier(a, b, c, d)
Derived from the Bezier curve in mathematics, this function takes parameters for start and end points (a
and d
) called “anchors,” and two middle points (b
and c
) called “handles.”
CSS also has five predefined instances of the cubic-bezier function based on the most commonly used timings:
Here’s how you would use the aliases in CSS:
#div1 {transition-timing-function: linear;}#div2 {transition-timing-function: ease;}#div3 {transition-timing-function: ease-in;}#div4 {transition-timing-function: ease-out;}#div5 {transition-timing-function: ease-in-out;}
The code below shows each alias from above replaced with its respective cubic-bezier function. Note that linear
only has two true points, since its middle points are also its start and end points. ease-in
has three true points, since its last two points are 1. ease-out
also has three true points, since its first two points are 0. You can match each instance to its respective curve, and notice how the number of points affects the curve shape.
#div1 {transition-timing-function: cubic-bezier(0,0,1,1);}#div2 {transition-timing-function: cubic-bezier(0.25,0.1,0.25,1);}#div3 {transition-timing-function: cubic-bezier(0.42,0,1,1);}#div4 {transition-timing-function: cubic-bezier(0,0,0.58,1);}#div5 {transition-timing-function: cubic-bezier(0.42,0,0.58,1);}
Keep in mind that in the code above, we are using transition-timing-function
which is used for transitions. There is also animation-timing-function
which works the same way, but applies to animations.
Transitions are triggered by changes in an element’s state (mouseover, click, drag, etc.). When you mouse over a button and it changes color smoothly, that is a hover transition. All transitions have an initial state and a final state, and for anything more elaborate, you will likely want to use animation, which we will cover later. For now, let’s begin with code structure:
transition: [*property] [*transition-duration] [transition-timing-function] [transition-delay];
The transition property takes two required parameters, and two optional parameters which have defaults. You can also pass multiple transitions by separating them with commas.
ease
.0
./*1*/ transition: background-color 2s;/*2*/ transition: background-color 2s 0.5s;/*3*/ transition: background-color 2s ease-in;/*4*/ transition: background-color 2s ease-out 0.5s;/*5*/ transition: background-color 2s, height 1s ease-in-out;/*6*/ transition: all 1s ease-out;
In the code above, you can see variations of the CSS transition property. The first five instances have a background color transition of two seconds. The second and fourth have a transition delay of 0.5 seconds. The fifth example has a second transition for height, and you can see how the transitions are comma-separated. The final example uses all
which means any visible change to the element will occur over the given period of time, in this case one second.
The code below is a simple example of an element using a CSS transition:
.glowAndGrow { height: 100px; transition: background-color 0.5s, height 1s;}
.glowAndGrow:hover { background-color: gold; height: 200px;<div class="glowAndGrow">This box glows and grows on hover</div>}
Keep in mind that CSS will also transition the element back to its initial state so, in the example above for instance, there’s no need to add a transition property for the hover case, unless you want the reverse transition to be different. (Sometimes you want an element to leave faster than it came in, especially large ones.)
Unlike transitions which are triggered by state changes, animations are used with CSS functions called keyframes. Also, animations can have more than just initial and final states, they can have many in between.
animation: [*animation-name] [*animation-duration] [animation-timing-function] [animation-delay] [animation-iteration-count] [animation-direction] [animation-fill-mode] [animation-play-state];
Like the transition property, the animation property takes two required parameters, as well as two optional parameters for timing and delay, and can also take multiple animations. However, because animations are more robust, they also have optional parameters for iteration count, direction, fill mode, and play state.
ease
.0
.infinite
which is the default.normal
.none
.running
.The second half of the animation code is the keyframe. A keyframe is a sequence of states which make up the animation:
@keyframes bounce { 0% { transform: scale(0.1); opacity: 0; } 60% { transform: scale(1.2); opacity: 1; } 100% { transform: scale(1); }}
.ball { animation: bounce 2s infinite;}
In the example above, the element begins in the first step of the sequence as transparent, and scaled down to 10% of its size. The second step is complete at 60% of the duration, and since this animation has a duration of two seconds, this means for the first 1.2 seconds of the animation, the element changes from transparent to opaque, and from 10% scale to 120% scale. Finally, in the last 0.8 seconds, it scales back to 100% of its size.
In a previous article, I wrote about how shade and tint in UI design are most pleasant when they mimic the physical properties of light. Likewise, when it comes to transitions and animations, the ideal experience is one which respects the laws of gravity.
With that said, unless you’re a game designer, be selective with your animation choices. A nice effect may be appealing at first, but after the thousandth time, the user may grow tired of seeing it.
Functional animation, on the other hand, never gets old. If you find a way to leverage animation to communicate with your users, then you will have found a real opportunity to maximize on a vibrant experience.
Below are some resourceful examples which may inspire you: