Advanced CSS3 2D and 3D Transform Techniques

Syed Fazle Rahman
Tweet

Gone are the days of using Flash and GIF images for creating animated graphics. It is time to show off some of the best CSS3 capabilities.

CSS3 transform has been there in the web for quite some time. Browsers like Mozilla, Google Chrome and Opera have full support for CSS3 2D and 3D transform techniques.

In this article you will learn:

  1. CSS3 2D Transform Techniques
  2. CSS3 3D Transform Techniques
  3. What is a Perspective?
  4. And many different transform functions

I have also prepared demos in which I will show you how to make:

  1. A 3D Card Flip
  2. A 3D Cube or a dice

The first question which might strike your mind is why do we need CSS3 transforms for animations and graphics? Well, the answer is very simple, faster web pages!

Yes, CSS animations are extremely light when compared with heavy GIF images and Flash content. And to add to it, Google does not rate Flash content highly in terms of SEO score. What if the animation used in your site was also read by robots and search engines? Wouldn’t that be an extra added feature from your SEO point of view?

Understanding CSS3 2D Transform

CSS3 2D transform gives you more freedom to decorate and animate HTML components. You have even more features to decorate text and more animation options for decorating div elements. CSS3 2D transform contains some basic functions like below:

  • translate()
  • rotate()
  • scale()
  • skew()
  • matrix()

Translate

Using the translate() function, you can move the div and text from their original position to any x-y co-ordinate without affecting other HTML components. For example:

div{ 
    transform: translate(20px,20px); 
}

The above code translates the div element 20px in x-direction and 20px in the y-direction.

translate

NOTE: x-y coordinates positioning in browsers is not same as used in geometry. A positive x value implies moving the object towards the right direction while a positive y value means moving it towards the bottom in y-direction. (0,0) co-ordinates refer to the top left corner of the browser.

For browsers like Opera, Chrome and older Firefox, you have to use –webkit-, -moz-, and –o- prefixes to the transform property. The CSS3 transform is not fully accepted by all browsers, but major browsers do support them with one of the above vendor provided prefixes.

Rotate

The rotate transform function rotates a specified HTML element to a given degree. The rotation is clockwise and starts from 0deg to 360deg. The rotation is done in the x-y plane.

div{ 
    transform: rotate(30deg); 
}

rotate

Scale

As the name suggests, it scales the old div to the new size as specified. This scaling takes place in both x and y direction. You can control the amount of scaling by specifying values, as parameters, to scale() function.

div{ 
    transform: scale(2,4); 
}

scale

Skew

When a skew transform function is applied to an element, the element bends to a specified amount as provided in the parameters list. You have to specify the angle value for x-direction as well as for the y-direction.

div{ 
    transform: skew(30deg,20deg); 
}

skew

Matrix

The work of matrix transform function is to combine all the above 2D transform function into one property. The values are in the form of linear transformation matrix.

div{ 
    transform: matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); 
}

matrix

CSS3 3D Transform

Now that you have gone through the basic of 2D transformation, understanding 3D transformation won’t be a difficult task for you. 3D transform includes Z-axis transformation of the HTML elements. We will go through each of the new properties used in 3D transformation.

  • translate3d(<translation-value>, <translation-value>, <length>) : it defines a 3D translation. It takes three parameters x, y and z values. The z value specifies the translation in the Z-axis.
  • translateZ(<length>) : To define the translation only in the Z-direction, use this transform function. It works similar to translateX() and translateY().
  • scale3d(<number>, <number>, <number>) : This function does the scaling in all the three dimensions. It takes three parameters as sx, sy and sz. Each value defines scaling in the respective direction.
  • scaleZ(<number>) : Just like the translate() function, we also have scaleZ() function which defines scaling only in one direction ie Z-direction. We also have scaleX() and scaleY() functions which also work similar to scaleZ() but in their respective directions.
  • rotate3d(<number>, <number>, <number>, <angle>) : It rotates a single HTML element by the specified angle provided in the last parameter in the [tx, ty, tz] vector specified by the first three numbers.
  • rotateX(<angle>), rotateY(<angle>) and rotateZ(<angle>) take only a single angle value to rotate in the respective axis.

Note: rotate3d(1,0,0,30deg) is equal to rotateX(30deg), rotate3d(0,1,0,30deg) is equal to rotateY(30deg) and rotate3d(0,0,1,30deg) is equal to rotateZ(30deg).

Perspective

The main part of the 3D Transform using CSS is the perspective. To activate a 3D space to make 3D transformation, you need to active it. This activation can be done in two ways as follows:

transform: perspective(500px);

or

perspective: 500px;

The functional notation is used to activate a single element whereas the second notation is used to apply perspective to multiple elements at a same time.

Transform Style

This is another important property in the 3D space. It takes two values: preserve-3d or flat. When the transform style value is preserve-3d then it tells the browser that the children element should also be positioned in the 3D space. On the other hand when the value of this property is flat, it indicates that children are present on the plane of the element itself.

Let’s start working

In this section, we will try to learn how to activate the 3D space and apply 3D transform different functions as stated above. In the below program we will create a blue square figure and then rotate it by 30 degrees in Y axis.

HTML

<section id="blue" class="container"> 
    <div></div> 
</section>

CSS

/* styling a container of size 200px X 200px that will contain the object */ 
.container{ 
    width:200px; 
    height:200px; 
    margin:40px auto; 
    position:relative; 
}
/* activating the 3D space */ 
#blue{ 
    perspective: 600px; 
} 
/* coloring the box and rotating it by 30 degrees in the 3D space */ 
#blue .box{ 
    background:blue; 
    transform: rotateY(30deg); 
    -moz- transform: rotateY(30deg); 
    -webkit- transform: rotateY(30deg); 
    -o- transform: rotateY(30deg); 
}

test1

Similarly you can apply different translate(), scale() and rotate() functions to the above figure and see how the figure orientation changes. I have given a screenshot below that shows a translateZ()  transformation.

test2

CSS3 3D Transform Demos

1) Card Flip

Now that we have understood the 2D and 3D transformation basics, we will make some practical demos and see how we can use them in day to day websites. I will show you how to make a card flip animation using CSS3 3D transform. The card has Apple’s logo on the front side and Samsung’s logo on the back, and when it flips it reveals SitePoint’s logo. Interesting isn’t?

flip1 flip2 flip3

HTML

<section class="container"> 
    <div id="card"> 
    <figure></figure>
    <figure></figure> 
</div> </section> 
<a href="#">flip it!</a>

CSS

/* Design container */ 
.container { 
    width: 250px; 
    height: 250px; 
    position: relative; 
    margin: 40px auto; 
    border: 1px solid #999999; 
    -webkit-perspective: 600px; 
    -moz-perspective: 600px; 
    -o-perspective: 600px; 
    perspective: 600px; 
}

The container is a square and each side measures 250px. We have also given margin to position the container to the center of the screen. To activate the 3D space we have also set the prospective property to 600px. As this is the main container I have set the background image as the SitePoint’s logo. Now, when the card flips, this background will be revealed.

CSS

/* styling card element */ 
#card { 
    width: 100%; 
    height: 100%; 
    position: absolute; 
    -webkit-transition: -webkit-transform 1s; 
    -moz-transition: -moz-transform 1s; 
    -o-transition: -o-transform 1s; 
    transition: transform 1s; 
    -webkit-transform-style: preserve-3d; 
    -moz-transform-style: preserve-3d; 
    -o-transform-style: preserve-3d; 
    transform-style: preserve-3d; 
}

Since height and width are set to 100%, the card div takes the dimensions of the parent container element. We have defined how long the transformation should take place with the transition property. It is set to 1s to animate the flipping for 1 second. The transform-style property makes sure that the children elements of this card div also have their 3D spaces activated. By default if the parent element’s 3D space is activated then only its direct children inherit the 3D activation. So in this example transform-style tells the children of the child div to inherit the 3D activation.

CSS

/* styling figure elements */ 
#card figure { 
    display: block; 
    height: 100%; 
    width: 100%; 
    position: absolute; 
    margin:0px; 
    -webkit-backface-visibility: hidden; 
    -moz-backface-visibility: hidden; 
    -o-backface-visibility: hidden; 
    backface-visibility: hidden; 
}

We have set backface-visibility property as hidden so the card is opaque and not transparent. You can also try setting it to transparent and see what effect you get.

CSS

#card .front {

    background: url('apple.jpg');

}

#card .back {

    background: url('samsung.jpg');

    -webkit-transform: rotateY( 180deg );

    -moz-transform: rotateY( 180deg );

    -o-transform: rotateY( 180deg );

    transform: rotateY( 180deg );

}

We have used two images, apple.jpg and samsung.jpg, as the background of the front figure and back figure.

Now that we have almost set everything, we need another class called “flipped” and set the transform property. This class will be set dynamically on the client side using any client-side scripting. I have used jQuery in this case. The “flipped” class styles are set as below:

CSS

#card.flipped { 
    -webkit-transform: rotateY( 180deg ); 
    -moz-transform: rotateY( 180deg ); 
    -o-transform: rotateY( 180deg ); 
    transform: rotateY( 180deg ); 
}

To run the animation, add an extra HTML link tag or a button and set the click event as follows:

jQuery Code

$(document).ready(function(){ 
    $("a").click(function(){ 
        $("#card").toggleClass("flipped"); 
    }); 
});

As you can see, we have used the click property of the link and have set a callback function. The task of the function is to toggle the class of the card div to “flipped”.

Congrats! You’ve made the card flip animation. Go to the browser and see the animation. Wasn’t that easy? :)

Live Demo

2) A 3D Rotating Cube

Let’s try something more complicated now. This time we will have six faces instead of only two. We will style each face, set them to proper orientation and finally animate. Each face of the cube will show the face number.

cube1 cube2 cube3
cube4 cube5

HTML

<section class="container"> 
    <div id="cube"> 
        <figure>1</figure> 
        <figure>2</figure> 
        <figure>3</figure> 
        <figure>4</figure> 
        <figure>5</figure> 
        <figure>6</figure> 
    </div> 
</section> 
<a href=”#”>Rotate it!</a>

Now we have the basic HTML structure of the cube. The main div, “cube” has six child “figure” elements for each side of the cube. Let’s start styling each of them.

CSS

/* First the container styles */ 
.container { 
    width: 200px; 
    height: 200px; 
    position: relative; 
    -webkit-perspective: 1000px; 
    -moz-perspective: 1000px; 
    -o-perspective: 1000px; 
    perspective: 1000px; 
    margin: 0 auto 40px; 
    border: 1px solid #CCC; 
}

Mark that we have activated the 3D space using the perspective property.

CSS

#cube { 
    width: 100%; 
    height: 100%; 
    position: absolute; 
    -webkit-transform-style: preserve-3d; 
    -moz-transform-style: preserve-3d; 
    -o-transform-style: preserve-3d; 
    transform-style: preserve-3d; 
    -webkit-transform: translateZ( -100px ); 
    -moz-transform: translateZ( -100px ); 
    -o-transform: translateZ( -100px ); 
    transform: translateZ( -100px ); 
    -webkit-transition: -webkit-transform 0.5s; 
    -moz-transition: -moz-transform 0.5s; 
    -o-transition: -o-transform 0.5s; 
    transition: transform 0.5s; 
}

For the cube, we have used the same preserve-3d to transform property as we did in the card flip example. One more thing which we did in this example was translating the whole cube -100px in the z-direction. Later in this example we will see that, the front facing side of the cube 100px in the z-direction is always translated 100px to the front. So, in order to make the text appear hazy, we have moved the whole cube -100px back.

CSS

#cube figure { 
    width: 196px; 
    height: 196px; 
    display: block; 
    position: absolute; 
    border: 2px solid black; 
    line-height: 196px; 
    font-size: 120px; 
    font-weight: bold; 
    color: white; 
    text-align: center; 
    margin:0px; 
}

The above styles will set the general CSS of each side. They should be square in dimensions and have a black border of 2px.

CSS

/* Applying a unique color to each face */ 
#cube .front  { background: hsla(   0, 100%, 50%, 0.7 ); } 
#cube .back   { background: hsla(  60, 100%, 50%, 0.7 ); } 
#cube .right  { background: hsla( 120, 100%, 50%, 0.7 ); } 
#cube .left   { background: hsla( 180, 100%, 50%, 0.7 ); } 
#cube .top    { background: hsla( 240, 100%, 50%, 0.7 ); } 
#cube .bottom { background: hsla( 300, 100%, 50%, 0.7 ); }

CSS

/* Giving the desired orientation to each side of the cube */ 
#cube .front  { 
    -webkit-transform: rotateY(   0deg ) translateZ( 100px ); 
    -moz-transform: rotateY(   0deg ) translateZ( 100px ); 
    -o-transform: rotateY(   0deg ) translateZ( 100px ); 
    transform: rotateY(   0deg ) translateZ( 100px );
} 
#cube .back   { 
    -webkit-transform: rotateX( 180deg ) translateZ( 100px ); 
    -moz-transform: rotateX( 180deg ) translateZ( 100px ); 
    -o-transform: rotateX( 180deg ) translateZ( 100px ); 
    transform: rotateX( 180deg ) translateZ( 100px );
} 
#cube .right  { 
    -webkit-transform: rotateY(  90deg ) translateZ( 100px ); 
    -moz-transform: rotateY(  90deg ) translateZ( 100px ); 
    -o-transform: rotateY(  90deg ) translateZ( 100px ); 
    transform: rotateY(  90deg ) translateZ( 100px ); 
} 
#cube .left   { 
    -webkit-transform: rotateY( -90deg ) translateZ( 100px ); 
    -moz-transform: rotateY( -90deg ) translateZ( 100px ); 
    -o-transform: rotateY( -90deg ) translateZ( 100px ); 
    transform: rotateY( -90deg ) translateZ( 100px ); 
} 
#cube .top    { 
    -webkit-transform: rotateX(  90deg ) translateZ( 100px ); 
    -moz-transform: rotateX(  90deg ) translateZ( 100px ); 
    -o-transform: rotateX(  90deg ) translateZ( 100px ); 
    transform: rotateX(  90deg ) translateZ( 100px ); 
} 
#cube .bottom { 
    -webkit-transform: rotateX( -90deg ) translateZ( 100px ); 
    -moz-transform: rotateX( -90deg ) translateZ( 100px ); 
    -o-transform: rotateX( -90deg ) translateZ( 100px ); 
    transform: rotateX( -90deg ) translateZ( 100px ); 
}

Now we have a 3D non-rotating cube ready with us. Finally we have to write transition style for each side which we will implement by applying right class using jQuery dynamically.

CSS

#cube.show-front  { 
    -webkit-transform: translateZ( -100px ) rotateY(    0deg ); 
    -moz-transform: translateZ( -100px ) rotateY(    0deg ); 
    -o-transform: translateZ( -100px ) rotateY(    0deg ); 
    transform: translateZ( -100px ) rotateY(    0deg ); 
} 
#cube.show-back   { 
    -webkit-transform: translateZ( -100px ) rotateX( -180deg ); 
    -moz-transform: translateZ( -100px ) rotateX( -180deg ); 
    -o-transform: translateZ( -100px ) rotateX( -180deg ); 
    transform: translateZ( -100px ) rotateX( -180deg ); 
} 
#cube.show-right  { 
    -webkit-transform: translateZ( -100px ) rotateY(  -90deg ); 
    -moz-transform: translateZ( -100px ) rotateY(  -90deg ); 
    -o-transform: translateZ( -100px ) rotateY(  -90deg ); 
    transform: translateZ( -100px ) rotateY(  -90deg ); 
} 
#cube.show-left   { 
    -webkit-transform: translateZ( -100px ) rotateY(   90deg ); 
    -moz-transform: translateZ( -100px ) rotateY(   90deg ); 
    -o-transform: translateZ( -100px ) rotateY(   90deg ); 
    transform: translateZ( -100px ) rotateY(   90deg ); 
} 
#cube.show-top    { 
    -webkit-transform: translateZ( -100px ) rotateX(  -90deg ); 
    -moz-transform: translateZ( -100px ) rotateX(  -90deg ); 
    -o-transform: translateZ( -100px ) rotateX(  -90deg ); 
    transform: translateZ( -100px ) rotateX(  -90deg ); 
} 
#cube.show-bottom { 
    -webkit-transform: translateZ( -100px ) rotateX(   90deg ); 
    -moz-transform: translateZ( -100px ) rotateX(   90deg ); 
    -o-transform: translateZ( -100px ) rotateX(   90deg ); 
    transform: translateZ( -100px ) rotateX(   90deg ); 
}

Finally we are ready to write the callback function using jQuery. The callback will triggered once the “Rotate!” link is clicked.

jQuery

$(document).ready(function(){ 
    var ctr=0; 
    var panel=""; 
        $("a").click(function(){ 
            ctr++; 
            if(ctr==1){ 
                $("#cube").toggleClass("show-back"); 
                $("#cube").removeClass(panel); 
                panel="show-back"; 
            } 
            if(ctr==2){ 
                $("#cube").toggleClass("show-right"); 
                $("#cube").removeClass(panel); 
                panel="show-right"; 
            } 
            if(ctr==3){ 
                $("#cube").toggleClass("show-left"); 
                $("#cube").removeClass(panel); 
                panel="show-left";
            } 
            if(ctr==4){ 
                $("#cube").toggleClass("show-top"); 
                $("#cube").removeClass(panel); panel="show-top"; 
            } 
            if(ctr==5){ 
                $("#cube").toggleClass("show-bottom"); 
                $("#cube").removeClass(panel); 
                panel="show-bottom"; 
            } 
            if(ctr==6){ 
                $("#cube").toggleClass("show-front"); 
                $("#cube").removeClass(panel); 
                panel="show-front"; ctr=0; 
            } 
        }); 
});

Live Demo

Congrats! You have made it through this demo, too! I hope you have understood what CSS3 transform is and how we can use it in our websites to make animations.

Some of other possible implementations of CSS3 3D transform could be a slider, an image carousel, an animated image album like Google+ photo album, etc.

And if you enjoyed reading this post, you’ll love Learnable; the place to learn fresh skills and techniques from the masters. Members get instant access to all of SitePoint’s ebooks and interactive online courses, like HTML5 & CSS3 For the Real World.

Comments on this article are closed. Have a question about CSS? Why not ask it on our forums?

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://reviewhuluplus.org/ Clayton Fairclough

    Thanks for the tutorial and tips. I tried it and still very confusing hopefully I could perfect this.

    • http://www.extremecss.com/ Syed Fazle Rahman

      Yes, it might be difficult but as you practice it more you will see a vast area of animation is out there to explore. The most important thing which I want to convey through this article was that we can stop depending on images for animations on webpages.

  • Euan Williamson

    Hi Fazle,

    I think I understand your tutorial, but I’m more a designer than a coder, my problem ;-)

    Would it be easy to place images on the cube faces?
    Would it be easy to make a solid with different face dimensions, eg
    6 x 6 x 3 units as its relative dimensions?

    I appreciate that the word easy above might need to be changed to possible.

    Many thanks, Euan

    • http://www.extremecss.com/ Syed Fazle Rahman

      Hello Euan,

      Yes of course it is easy to place images in place of numbers on the cube faces. You can set the images as the background and remove the numbers. Dimensions are not a constrain, you can customize the cubes as per your requirements.

      Thanks.

  • Diego Díaz

    Great! Thanks for this awesome tutorial, i suppouse IE is off the chart isn’t it?

  • http://shodannews.wordpress.com/ Aulbath

    Love the cube, excellent stuff.
    If I understand it correctly, the trigger is just the a-Tag, right? So, it’s probably possible to target each of the 6 states with a specific a-Tag, isn’t it? Like, I have button “6” and it jumps to “6” on the cube – would I need additional transitions if I came from different states, like “2”, “3” and so on? I think this would make a niffty addition to menus and other things, but I am struggling with adapting the callback-function. Maybe you can help or give some pointers?

  • Ed Brandon

    I think one key item is missing. Translations happen around a point and that point is usually the centre of the item. To translate around some other point in the item requires one more property, the transform-origin (see: http://www.w3.org/TR/2012/WD-css3-transforms-20120911/#transform-origin-property).

    For me, the sad part is the lack of complete, or uniform, support for this across browsers for translations. But then, this part of CSS3 is not yet ready. I’m waiting (im)patiently!

  • http://oscaralderete.com Oscar

    Great tut.
    Thanks to share!

  • walter savage

    Great tutorial! Thanks.

  • http://www.timothysolomon.co.za Timothy

    Impressive. Thanks for the detailed tutorial!

  • http://whetstonedesign.co.uk Jim

    Very nice simple tutorial, I can see lots of opportunities here once support is more unversal, thank you!

  • https://twitter.com/DigitalAmoeba Alan Howshall

    Nice CSS transform tutorial and demos :D

    One piece of feedback is that you’ve over simplified the HTML source code you show in both main examples, by not showing the class= attributes you’ve applied to the HTML tags

    …that means unless/until people look at the real HTML in your demo pages they may think it’s ‘magic/inherited’ where you’ve got CSS targets like ‘#card .front’ and ‘#cube .right’ from.

    • http://www.extremecss.com/ Syed Fazle Rahman

      thanks for the suggestion! :)

  • http://www.livetagwebdesign.co.uk Live Tag Web Design

    thank you so much for this, the card flip is something i’ve been trying to execute myself for a while, really good tutorial

  • Liam

    Just a small point, Opera does not yet support 3d transformations: http://caniuse.com/#feat=transforms3d

  • http://www.courtthree.co.uk Dan Norman

    Blown away by the dice mate, that is seriously impressive. I know the web has along way to go before this kind of thing is a realistic mainstream option but, nevertheless, this is amazing. And as a developer who had to abandon Flash 2 or 3 years ago to pursue HTML5, this is very exciting…