With CSS3 be get some great new functions to use that are now accessible pretty easy. These are not only rounded corners or shadows but also transitions and full animations that let you do things that were only possible with JavaScript some time ago.

In the footer of this website I use CSS3 3D-transitions for rotating two images. There is a front- and a back-site for that image. Through animation on click it looks like these images are rotating.
I’m not the first one using this technique. I got inspired by Google+. They are using it for rotation of the profile-picture but in another way with JS.

So… Let’s start this little tutorial. We will be do all the stuff with pure CSS which is a bit tricky and – as you may guess – this will not work with all of the browsers that are in use. But let’s take a look.


What the HTML will look like:

<div class="animate-wrap">
  <input type="radio" id="ani-1" name="animation" checked="true">
  <input type="radio" id="ani-2" name="animation">
  <div class="animate">
    <label for="ani-2" class="front">
      <img src="" width="220" height="220" alt="A photo of me.">
    <label for="ani-1" class="back">
      <img src="" width="220" height="220" alt="Another photo of me.">

You may wonder why there are those two radio-buttons and labels included in the markup. Well, let me explain this: When you click on a label, the radio-button with the ID defined in the for-attribute will be activated. With CSS we can then define rules relaying on the :checked pseudo-class.

Chris Coyier also used this technique to build CSS-only tabs. In this article you will find some more information about how and why to use radio-buttons for this approach. Chris also wrote down pros and cons, stuff you should consider and so on.


As I wrote, the idea of flipping images with CSS is not exactly what you would call new. So to get the CSS-part of it you can also visit this nice demo-page and check out the source code on Github.

Mh, now let’s have a look at the CSS. One thing should be pretty obvious: We are using CSS3 for this tutorial, so there are some issues with vendor-prefixes. At the time of writing it will only work in Webkit-browsers as this is the only engine which supports 3D transforms for some time now. As mentioned by Daniel Baron on Twitter today the nightlies of Firefox will support it too. I checked on Firefox 10.0a1 (FF Nightly as of today) and it works like a charm.
Anyway: we will find a way to make it look ok in all of the browsers.

/* Wrapper */
.animate-wrap {
  position: relative;
  width: 220px; height: 220px;
  background-color: #aaa;
  -webkit-perspective: 1000;
     -moz-perspective: 1000;
          perspective: 1000;
/* Inputs */
.animate-wrap input {
  display: none;
.animate-wrap [type="radio"]:checked + .animate {
  -webkit-transform: rotateY(180deg);
     -moz-transform: rotateY(180deg);
          transform: rotateY(180deg);
/* Image-Wrapper */
.animate {
  -webkit-transform-style: preserve-3d;
     -moz-transform-style: preserve-3d;
          transform-style: preserve-3d;
  -webkit-transition: all 0.5s ease-out;
     -moz-transition: all 0.5s ease-out;
          transition: all 0.5s ease-out;
/* Labels */
label {
  position: absolute; top: 0; left: 0; z-index: 2;
  -webkit-backface-visibility: hidden;
     -moz-backface-visibility: hidden;
          backface-visibility: hidden;
.back {
  -webkit-transform: rotateY(180deg);
     -moz-transform: rotateY(180deg);
          transform: rotateY(180deg);
.front {
  z-index: 1;

Let’s break this down: First of all we have the styles for the wrapper. The important bit here is the perspective-keyword. As the name it self indicates it adds some perspective to the animated items.

Input-fields are hidden. By detecting which input-field is checked we start the animation by adding transform with a value of rotateY(180deg) to the label that is supposed to be animated. This indicates that the element will be rotated around the Y-axis or as the spec describes it

rotateY(<angle>) specifies a clockwise rotation by the given angle about the Y axis.

Another important bit that keeps the animation running like it shout is the transform-style-property which defines that the animation should be performed in a 3D-context via the value preserve-3d.

You will get a nice overview of these attributes named here by reading this article about how to animate a 3D-cube with CSS.

In order to prevent a kind of flashing while the animation takes place I added the backface-visibility property.


We are finished with the CSS3 3D-transforms now. But we want to have some more browser-compatibility I think. Therefore we will add some JavaScript to the code which adds and removes a class front to the image that should be displayed.

if (!Modernizr.csstransforms3d) {
  $('label').click(function() {
    $('.animate .front').removeClass('front');

As you can see the JS-snipped uses Modernizr to detect if CSS3 3D-transform are supported or not. If not JavaScript listens to the clicks on label elements and adds a class to the clicked one while removing the “old” one. This snipped is depending on jQuery as I personally use it for like every page I’m doing. But there are ways to do it without any library… You’re smart, you know that.

So… looks like we’re done here. If you have something to change for this little tutorial, please let me know in the comments or via email.

Download the files       Demonstration