Animation Using CSS Transforms

The examples on this page will work properly in Safari, Chrome and
Opera. In Firefox prior to version 4 you will see the transforms, but
without any animation. Transformation effects also work now in Internet
Explorer 9 using the -ms- vendor prefix.The implementation of animation in CSS involves setting up a transformation to take place in response to a
mouseover or other event. Then, rather than applying the effect
instantly, we assign a transition timing
which applies the transformation/s over a set time
period.Firefox and Opera now support these transforms with an almost
identical syntax – just replace -webkit with -moz or
-o in the examples below and you will see the same effects.
And you can use -ms to enable transformation effects for

1. Introducing CSS Transformations

The effect of a CSS Transform is to modify the appearance of an
element in the browser by translation, rotation or other means. When
defined in a style sheet transformations are applied before the page is
rendered, so you don’t actually see any animations taking place.
Transforms can also be applied as a mouseover or similar effect
which you can see in the next section.

Apple’s proposal for CSS Transformations calls for
the ability to change the perspective and work in three dimensions, but
that’s some way away yet. Even the features demonstrated here won’t
appear in other browsers until they’re approved by the standards body
who are still quibbling over CSS3 modules.

Below we’ve placed four identical DIV’s styled as a 100 x 60 pixel
box with a 2 pixel border. Subsequently, each element has been
transformed in some way using the -webkit-transform property as

box 1 Translated to the right: -webkit-transform: translate(3em,0);
box 2 Rotated 30 degrees with the clock: -webkit-transform: rotate(30deg);
box 3 Translated to the left and down: -webkit-transform: translate(-3em,1em);
box 4 Scaled to twice its original size: -webkit-transform: scale(2);
box 1
box 2
box 3
box 4

Without the translations, and the red border on the second box, you
would see just four identical boxes labelled one through four. What you
see in supported browsers (Safari, Chrome, Firefox, Opera), however,
will be more like this:

Of note is the fact that the text is still selectable in transformed
elements, even when rotated, and that scaling an element affects other
properties including border widths and font sizes and not just the

2. Animating your Transforms

While CSS Transformation in itself is a powerful tool for developers
(though I shudder to think what would happen if it was more widely
available), the ability to animate the same effects using
-webkit-transition is far more exciting. Move your mouse over
the following four boxes for a demonstration:

box 1
box 2
box 3
box 4

What you see above is the four boxes from the previous section, in
their default states. When you mouseover any of the boxes, however, the
CSS transformation is applied as a one second animation. When the mouse
moves away the animation is reversed, taking each box back to its
starting position and state. And we achieve this without using
JavaScript – only HTML and CSS!

If you think that’s cool, realise that CSS Animation can be applied
not just to the transforms, but also to other CSS properties including:
opacity, colour and a bunch of other properties.

In the next example the box on the left begins as small and green
with square corners, while the one on the right is larger, with a red
border and rounded corners. Hovering over either of the boxes will
trigger an animation that makes box 1 take on the appearance of box 2
and vice versa.

box 1
box 2

Again, we’re still only using HTML and CSS to make this happen.
Without CSS Transforms the two boxes will still change their
border-color, and possibly also the border-radius, but
it happens immediately rather than as a one second animation.

For more advanced examples you can read our new article on using JavaScript to trigger the

3. Multiple Transforms on one element

To apply more than one transformation to a single element simply list
them one after another separated by spaces. The submenu for example at
the top right of this page has the following styles:

<style type="text/css">

#submenu {
background-color: #eee;
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
-ms-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
#submenu:hover {
background-color: #fc3;
-webkit-transform: rotate(360deg) scale(2);
-moz-transform: rotate(360deg) scale(2);
-o-transform: rotate(360deg) scale(2);
-ms-transform: rotate(360deg) scale(2);
transform: rotate(360deg) scale(2);


This means that when you hover over the submenu, it will change
colour, rotate and double in size over a period of one second as shown


These effects are now available in the latest public release of
Safari, so in principle all OSX users will be able to see these effects.
Whether it’s a good idea to add them to your website I’ll leave up to

Update: Thanks to misterbisson those without WebKit can now see a
screencast of the menu animation:

4. Animations in action

Now here’s another example of the kind of fun we can have in
combining different effects into single animation. Perhaps you can
already work out what’s going to happen based on the CSS?

<style type="text/css">

#outerspace {
position: relative;
height: 400px;
background: #0c0440 url(/images/outerspace.jpg);
div.rocket {
position: absolute;
bottom: 10px;
left: 20px;
-webkit-transition: all 3s ease-in;
-moz-transition: all 3s ease-in;
-o-transition: all 3s ease-in;
-ms-transition: all 3s ease-in;
transition: all 3s ease-in;
div.rocket img {
-webkit-transition: all 2s ease-in-out;
-moz-transition: all 2s ease-in-out;
-o-transition: all 2s ease-in-out;
-ms-transition: all 2s ease-in-out;
transition: all 2s ease-in-out;
#outerspace:hover div.rocket {
-webkit-transform: translate(540px,-200px);
-moz-transform: translate(540px,-200px);
-o-transform: translate(540px,-200px);
-ms-transform: translate(540px,-200px);
transition: all 2s ease-in-out;
#outerspace:hover div.rocket img {
-webkit-transform: rotate(70deg);
-moz-transform: rotate(70deg);
-o-transform: rotate(70deg);
-ms-transform: rotate(70deg);
transform: rotate(70deg);


rocket animation


If you’re using Safari 3 you may notice some problems with the
animation, particularly when it reverses after you move the mouse away,
but in the latest version of WebKit it’s already much smoother. Also
the animation in Opera is a bit erratic, with not all the elements being

The dotted outline that appears during the animation shows the
placement of the DIV containing the rocket image. This DIV translates
across the screen while the image inside is rotated. Simple!

For the browser-impaired what’s happening is that when you move the
mouse over the space background, the rocket translates from the bottom
left to the top right over a period of 3 seconds (translate())
and also rotates 70 degrees in a clockwise direction over the first 2
seconds (rotate()). The effect is rudimentary, but shows the

To have more control over the animation paths and timing, you can
set up WebKit Keyframes. They also
allow the animations to run automatically rather than in response to
mouse events.

5. Multiple timing functions



In this example we are applying four different transitions using four
different timing functions.

When you :hover over the area to the right the blue box will
spin, change color from red to blue and move from the top left of the
containing box to the bottom right over two seconds.

The first thing you will notice is that that the movement of the box
appears to be curved rather than straight. That’s because we’ve used
the ease-out timing
for the horizontal translation and ease-in for
the vertical.

The other feature is that the colour change from blue to red takes
place over the first second of the two section transition, followed by
the rotation which takes place over the second second.

The trick to this is that instead of defining the
-webkit-transition as a single property, you can break it up
into component parts. We’ve also made use of
-webkit-transition-delay which allows you to set the starting
point of different effects.

Here are the relevant CSS statements:

#block {
background: blue;
-webkit-transition-property: left, top, background, -webkit-transform;
-webkit-transition-duration: 2s, 2s, 1s, 1s;
-webkit-transition-timing-function: ease-out, ease-in, linear, ease-in-out;
-webkit-transition-delay: 0, 0, 0, 1s;
#stage:hover #block {
left: 100px;
top: 100px;
background: red;
-webkit-transform: rotate(360deg);

The rules affecting the background colour transition have been

Firefox does not appear to support the
transition-delay option
requires units to be specified even
for zero values in -moz-transition-delay, so 0s, 0s, 0s, 1s will work for the example above.

6. Hover over one element to affect another

A couple of people have asked about triggering animations in
relation to a click or hover event elsewhere on the page. With
JavaScript this can be done by using an event handler to set or change
the className of the element to be animated, and to have a
transformation or keyframes associated with the new class.

Using CSS there are some options for targeting related elements.
These involve selectors such as the > (child), +
(adjacent sibling) and ~ (general sibling) combinators.

The preceding examples all required a direct hover event
either on the element itself or on its container, wheras in this example
the blue box is animated only when you hover over its sibing, the red



The relevant CSS code is as follows. Note that we are using the
+ adjacent sibling combinator to target #box2 when
#box1 experiences a hover event. The ~ combinator may
be more flexible in letting you target elements that are further away
from the triggering element (some examples).

#box2 {
position: absolute;
left: 120px;
background: blue;
#box1:hover + #box2 {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-o-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
left: 627px;
background: yellow;

Of course we can still animate the first box at the same time as
targeting it’s sibling or siblings:



Just be sure not to move the hovered element out from under the
pointer or the animation will stop/reverse.

These examples work more or less as intended in WebKit (Safari,
Chrome), Firefox and Opera. They may also work in IE10 or higher – if
anyone can confirm that please let us know.

7. References

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s