Using CSS3 keyframe animation to create a swinging image
Created: Jan 4th, 15'
In this short tutorial, we'll see how easy it is to create an image that swings like a pendulum continuously using CSS3 keyframes
animation. Such an effect has become popular with signage and "discount" images, drawing subtle attention to them. Here's an example:
Image credits: Here
The CSS and HTML code
The source code is worth a thousand words, so lets first look at the CSS and HTML that comprise the above example before explaining how it all works:
The CSS:
@-webkit-keyframes swinging{ 0%{-webkit-transform: rotate(10deg);} 50%{-webkit-transform: rotate(-5deg)} 100%{-webkit-transform: rotate(10deg);} } @keyframes swinging{ 0%{transform: rotate(10deg);} 50%{transform: rotate(-5deg)} 100%{transform: rotate(10deg);} } .swingimage{ -webkit-transform-origin: 50% 0; transform-origin: 50% 0; -webkit-animation: swinging 3.5s ease-in-out forwards infinite; animation: swinging 3.5s ease-in-out forwards infinite; }
The HTML:
<img class="swingimage" src="wintersale.png" />
@keyframes
rule and animation
property syntax
To create the swinging animation, we define a @keyframes
rule specifying how our animation should unfold at various points. The syntax for @keyframes
is as follows:
@keyframes animation-name{ keyframes-selector: {css styles} keyframes-selector: {css styles} " }
Here's a quick breakdown of the parts that make up this syntax:
Value | Description |
---|---|
anmation-name | An arbitrary string to identify this @keyframes animation |
keyframes-selector |
A percentage value (0% to 10%) donating the point in the animation the enclosed styles should be applied at.
You can also use the two keywords " from {background: white;} to {background: black;} |
css styles | One or more CSS styles (each separated by a semi colon) specifying the style at this point in the animation. |
Keyframes animations are supported in IE10+, FF5+, Chrome, Opera 12+, and Safari 4+. Within this list, the older versions of Chrome, and Safari require a vendor prefix in front of @keyframes
in order to work properly, hence the two versions of the same @keyframes
animation definition in our example above (@-webkit-keyframes swinging{}
and @keyframes swinging{}
).
Note on prefixes: There are other vendor specific prefixes you may need to add in front of your CSS3 rule or property such as keyframes
or transition
to cover all your bases. The major vendor prefixes are -webkit-, -moz-, -ms-, and -o-. In general however only -webkit- is needed these days to cover Safari browsers still stubbornly hanging on to prefixed versions of CSS3 properties. The important thing is to test your CSS against your target browsers to see if adding a prefix makes a difference. You can use a tool such as autoprefixer to intelligently add vendor prefixes to default CSS3 rules and properties in your CSS.
Once the @keyframes
animation has been defined, we use CSS's animation
property to reference that animation inside a CSS element or class selector, such as:
.swingimage{ -webkit-transform-origin: 50% 0; /* for Safari and older Chrome */ transform-origin: 50% 0; -webkit-animation: swinging 3.5s ease-in-out forwards infinite; animation: swinging 3.5s ease-in-out forwards infinite; }
Here we're adding the animation
property inside a CSS class (and then assigning the class to the target element). The animation
property is shorthand for the following animation related properties:
property | Description |
---|---|
animation-name | The @keyframes animation name to be associated with this animation. Defaults to none. |
animation-duration | The duration (integer) of the animation suffixed with either "s" or "ms" for seconds or milliseconds. Defaults to 0s, which means the animation won't run. |
animation-timing-function | Sets the timing function used to animate the @keyframe animation. Valid values include "ease ", "ease-in ", "linear ", steps() etc. Defaults to "ease". |
animation-delay | The delay (integer) before the animation started, suffixed with either "s" or "ms" for seconds or milliseconds. Defaults to 0s. |
animation-iteration-count | Sets the number of times the animation should run before stopping. A value of "infinite " means forever. Defaults to 1. |
animation-direction |
Defines whether the animation should play as normal, in reverse, or alternate between the two. Possible values are:
|
animation-fill-mode |
Defines how the animation should apply styles to its target when the animation isn't playing anymore. Possible values are:
|
animation-play-state | Defines whether the animation is initially playing or not. Possible values are "running " or "paused ". Defaults to "running". |
Inside the animation
shorthand property, if a particular animation property value is omitted, the default value for that property will be used. Furthermore, the order of each property value inside animation in general isn't important, with the exception of the two time related properties (animation-duration
and animation-delay
)- if both are defined, animation-duration
should always proceed animation-delay
.
Revisiting the CSS for our swinging image
In our CSS for creating a swinging image, we have the following defined for our "swingimage
" class:
.swingimage{ -webkit-transform-origin: 50% 0; transform-origin: 50% 0; -webkit-animation: swinging 3.5s ease-in-out forwards infinite; animation: swinging 3.5s ease-in-out forwards infinite; }
Here you can see we've set the animation shorthand property to:
animation: swinging 3.5s ease-in-out forwards infinite;
That is to say, we want the swinging keyframes animation to run for 3.5 seconds for each cycle, using the "ease-in-out
" timing function, and for the target element to retain the last keyframe styles afterwards. With the target element keeping the last keyframe's styles at the end of the cycle, we create a seamless transition between the last and first keyframe styles when the next cycle begins. And last by not least, we want this animation to run for an infinite number of cycles.
Now lets turn our attention to the transform-origin
property inside the CSS class. It dictates the x-offset and y-offset origin where any CSS related transformation will take place, which in our swinging image will be the rotation of the image. In the demo image above, the "hinge" where the rotation should originate from is exactly midpoint horizontally inside the image, and at the top vertically:
This is why for our transform-origin
property value, we have the following:
transform-origin: 50% 0;
Lets consider a different image now with a hinge that's not dead center horizontally:
In this case, we'll want to adjust the transform-origin
value to 35% horizontally:
transform-origin: 35% 0;
Demo:
Image credits: Here
The transform-origin
property supports either an explicit length value (ie: px) or percentage as its unit, so to be even more precise, you could specify say 77px for the x-offset value instead of 35% here.
The best way to get a handle on keyframe animation and the animation property is to try out different values and see the changes. You can play around with the code for the two swinging images below: