CSS Transitions and transforms work beautifully for creating visual interactions based on single state changes. To have more control over what happens and when, you can use the CSS animation property to create easy CSS animation using @keyframes. This technique has a wide range of design application and can be used to build dazzling pre-loaders, interactive interfaces, effects or full-scale storytelling. In this tutorial you’ll learn how to apply what you know about CSS transitions to quickly master animation, and how to use @keyframes for applying various style rules to your element at different intervals.
If you missed it, check out Easy CSS Animation With Transition & Transforms to get your mind thinking about how your element should move. CSS transition and animation are almost the same, where animation can dig deeper by giving your element a defined timeline for when different style changes take effect.
CSS keyframes allow changes to run automatically and continuously, rather than just in response to mouse events the way transition does. They give us a way to change the CSS declarations on a given selector at any point during a state change or an event detected through jQuery (such as scrolling). Keyframes are paired with the
animation property to set the
direction instead of
transition. Properties such as
transform, if part of an animation, are then declared within the
To start, each
@keyframe rule gets a unique name:
This name is used on the element’s style to pair it with the animation:
.element animation: animation-name;
Inside it, you set a rule for a percentage representing the point along the animation’s timeline for the declared CSS styles to be rendered on the element:
@keyframes animation-name 0% color: pink; 50% color: yellow; 100% color: blue;
In this example, the element
div with a class of
element goes from pink to yellow to blue. You can also use
to when going between only two points:
@keyframes animation-name from color: black; to color: white;
Here is an example of applying this simple rule to a background color change on the
body animation: change-background 4s ease infinite;
See the Pen CSS @keyframes Color-changing Background by Vail Joy (@vailjoy) on CodePen.27486
Full Screen Demo
The @keyframes themselves do nothing without some instructions that define things like the duration, timing function and direction, which each work just like they do in the
transition property. These animation sub-properties can be declared in one
animation declaration using the following syntax:
animation: duration | timing-function | delay | iteration-count | direction | fill-mode | play-state | name;
Or set individually by appending animation- to the beginning of each sub-property:
animation-duration: 1s; animation-timing-function: ease; animation-delay: 2s; animation-iteration-count: infinite;
…You get the idea.
Not all of these sub-properties are required, but they do have to be in the right order so the browser can apply the timing value to the right thing, or distinguish the animation name from other keywords, for example. Here is a quick run-down of the sub-properties you’ll use the most:
duration– Sets how long the animation runs from start to finish.
timing-function– Sets how the animation moves along the timing “track”, ie ease, ease-in, linear, etc.
delay– how much time (if any) to wait before kicking off the animation sequence.
iteration-count– how many times to play the animation, or
infiniteto loop it.
See the Pen Animation Timing functions visualization by Vail Joy (@vailjoy) on CodePen.27486
Full Screen Demo
In addition to the property values we are already familiar with thanks to
transition, animation takes a
By default, animations go through one cycle, then end. The
animation-iteration-count sub-property value may be set using either a number representing how many times the animation should run, or the infinite keyword to run it indefinitely.
animation-direction subproperty does not define the visual direction of an animation (your style rules define position and start and end states) but rather tells the animation which order to run the keyframes. This sub-property can be set to
normalvalue plays an animation from beginning to end. The reverse value plays it backwards or bottom to top as the rules are written, starting at 100% and working backwards to 0%.
alternatevalue will play an animation forwards then backwards, and alternate-reverse plays it backwards, then forwards.
animation-fill-mode sub-property decides if the animation styles should remain visible before or after the animation plays.
By default (
normal), the styles defined inside the animation keyframes do not affect the element before or after the animation plays. Setting the fill-mode value is useful if you need the end-state of your animation to become the new state until something else happens, or to fix the abrupt change back to the original state (as you can see in our background change demo above). Here is a breakdown of what each value does:
backwards– Before the animation plays and there is a delay set, the styles of the initial keyframe (0%) are applied.
forwards– After the animation plays, the styles defined in the last keyframe (100%) remain active.
both– The animation will follow the rules for both forwards and backwards.
You’ll see how to use fill-mode on a hover effect to keep that abrupt flicker from happening below.
The play-state value can be set to
running. One useful way to implement
play-state is to set it to paused on hover. If you look at our first example above, hover over the bar highlighting each keyframe as it plays, and it will pause.
.highlight animation: move-highlight 4s linear infinite; .highlight:hover animation-play-state: paused;
Note you can used
animation: paused; or
animation-play-state: paused;, but it is always best to declare a specific sub-property when resetting or overriding a previous value on state change.
Use Animation and @keyframes to Create Shutter Effect on Image Hover
See the Pen Animation @keyframes in Image Hovers by Vail Joy (@vailjoy) on CodePen.27486
Full Screen Demo
This example demonstrates how you can create a “shutter” effect on an image gallery when the image is hovered. Unlike a simple hover effect using transition, this CSS animation uses keyframes to gradually change opacity on a pseudo-element while changing its size, and remove a CSS3 grayscale filter added to each image’s original state.
Here are the important bits of the CSS for the image wrapper and pseudo-element that will overlay it:
figure position: relative; overflow: hidden; margin: 0; height: 100%; width: 100%; filter: grayscale(.8); figure::before position: absolute; top: 50%; left: 50%; z-index: 2; display: block; content: ''; width: 0; height: 0; background: rgba(255,255,255,.2); border-radius: 100%; transform: translate(-50%, -50%); opacity: 0;
opacity set on these elements. These declarations define their default states before the animation is triggered.
figure:hover animation: bloom ease-in-out .75s forwards; figure:hover::before animation: circle .75s;
Now we set the
animation property for the event we want to trigger the animation. Using
:hover is the simplest – you could also set a special class name on an event detected with jQuery.
In the first animation, we link it to the
bloom keyframes, give it an
ease-in-out timing function that will play out over .75 seconds and then return to the original style thanks to the animation-fill-mode setting of
forwards – this ensures our effect doesn’t just blink back to the original grayscale effect. In our second animation, we link it to the
circle keyframes and tell it to play out over the same .75 seconds.
@keyframes bloom 0% filter: grayscale(.8); 40% filter: grayscale(.5); 100% filter: grayscale(0); @keyframes circle 0% opacity: .5; background: rgba(213,156,34,.2); 40% opacity: 1; background: rgba(213,34,160,.2); 100% width: 200%; height: 200%; opacity: 0;
bloom animation, we are taking the grayscale filter declared on the figure element our animation is set on from .8 to none. When the animation finishes, it stays at 0 thanks to our animation fill mode. If we didn’t set this, it would blink back to grayscale abruptly.
On our second animation
circle, we take the element opacity from half to full, change the color to a yellow then pink, then expand the element larger while bringing the opacity back to 0.
This is the basis for creating a simple “pulse” or “shutter” effect. Note that the element
opacity is separate from the color’s RGBA opacity!
Once you have the basics of CSS animation down, you can see how easy it is to come up with endless possibilities. Even still, many excellent code libraries and tools exist to help us implement CSS animations quickly. Here are a few of the best ones:
Previously, I showed you how to use Flexbox to create a split-screen layout, then use the animate.css library to animate the opening of the content pages and images. Animate.css provides several pre-made animations you can preview and then drop-in your project using a single class name. What’s more, it offers a great way to get started with learning how to apply and remove CSS classes from an element using jQuery. Be sure to check out that tutorial to learn how to kick off your animations on events like clicks or scroll points.
Cubic Bezier Tool
cubic-bezier.com provides a wonderful visual interface for making your own cubic bezier timing functions, and seeing the results in real time. The code snippet can be copied and pasted right into your stylsheets.
The CSS Animate web tool helps you generate full keyframe and animation codeblocks for a jumpstart on coding complex timelines. If you were ever into Flash, this might look familiar. Simply click a spot on the timeline, drag your element into position, set its animation properties then repeat for each new point selected on the timeline. Play back your completed code to refine, then copy/paste.
- CSS Animation Rocks – A Collection of beginner tutorials to help you master keyframe animation
- The Art of UI Animations – designer Mark Geyers online workshop on CSS animation, performance and tips
- Species in Pieces – mind-blowing examples of CSS animation in action
- Mars Landing – Mathew Gitchell’s implementation of @keyframes to create movement by changing margins
- CSS Hovering Fairy – Judith Neumann’s implementation of @keyframes to make a fairy’s wings flutter while she hovers