CSS 3D Transformations - Rotation

Chapter 43 9 mins

Learning outcomes:

  1. Rotation in the x-axis using rotateX()
  2. Rotation in the y-axis using rotateY()
  3. Rotation in the z-axis using rotateZ()
  4. The rotate3d() function

Introduction

In the previous chapter, CSS 3D Transformations — Translation, we saw 3D translations in CSS, performed via the translateZ() and translate3d() functions. Translation is one kind of 3D transformations in CSS, another one is rotation.

In this chapter, we shall explore the different functions used to rotate a given element in 3D space, and even see how those functions work. As before, all this 3D magic will be dependent upon the application of perspective in CSS.

Likewise, it's important for you to be aware of what perspective is and how it works before proceeding with this chapter.

Rotation in the x-axis

To rotate an element in the x-axis, where the x-axis acts as the pivot of rotation, we use the rotateX() transform function.

Syntactically, rotateX() is akin to rotate():

rotateX(<angle> | <zero>)

It takes a single argument specifying the rotation angle, which can either be an <angle> or just the value 0 (represented as <zero>).

Let's consider a quick example of rotateX().

In the following code, we create a square <div> (which is quite a casual activity for us by now in this unit):

<div></div>
div {
   width: 100px;
   height: 100px;
   background-color: blue;
}

Now, let's rotate this square in the x-axis by 45 degrees:

div {
   width: 100px;
   height: 100px;
   background-color: blue;
transform: rotateX(45deg); }

Notice how the square reduces in size — this is by virtue of the rotation. But the rotation isn't that clear, and that's because we can visualize it in 3D unless we bring perspective into the game.

So let's do that now, using the perspective() function and see the change:

div {
   width: 100px;
   height: 100px;
   background-color: blue;
transform: perspective(500px) rotateX(45deg); }

See how the square now seems to be rotated into the screen; it's top side is shorter in length indicating that it's in the distance while the bottom side is nearer to the viewer.

Keep in mind that a positive angle rotates the element towards the screen while a negative angle rotates it away from the screen.

Following this, let's try rotating the square above by a negative angle.

div {
   width: 100px;
   height: 100px;
   background-color: blue;
transform: perspective(500px) rotateX(-45deg); }

Quite expectedly, the rotation now gives the impression of being towards the viewer.

Simple, isn't it?

As a very quick recap, remember that a larger value of perspective() (or perspective, for that matter) leads to more pronounced transformations. And, by far, the best way to visualize this is in rotation.

Consider the following code, where we rotate our square <div> by the same 45 degrees angle, but this time the value of perspective() is 100px instead of 500px:

div {
   width: 100px;
   height: 100px;
   background-color: blue;
transform: perspective(100px) rotateX(45deg); }

Notice how the rotation is a bit more pronounced than before, thanks to the smaller value given to perspective(), which leads to a near-positioned perspective view point.

Try going even beyond this, experimenting with an even smaller value of perspective(). See the transformation you get!

These were fairly simple examples using rotateX(); now, it's time to use the function along with the transform-origin property.

In the following code, we perform the same 45 degrees rotation around the x-axis, as done above, but this time we change the transform-origin to the top edge of the <div>:

div {
   width: 100px;
   height: 100px;
   background-color: blue;
   transform: perspective(100px) rotateX(45deg);
transform-origin: top; }

Since the top edge is the new transform-origin here, rotating the <div> has it fixed at its top edge. Such a transformation can be used, for instance, to design a calendar transition.

Rotation in the y-axis

As the name suggests, the rotateY() function performs rotation in the y-axis.

Syntactically, rotateY() identical to rotateX():

rotateY(<angle> | <zero>)

Once again, positive values rotate an element backwards while negative values rotate an element forwards.

Let's try experimenting with rotateY().

Here's our original square <div>:

Below, we transform it by rotating it around the y-axis by an angle of 45 degrees:

div {
   width: 100px;
   height: 100px;
   background-color: blue;
transform: perspective(500px) rotateY(45deg); }

Since the left edge of the square is larger in size than the right edge, it's clear to us that the left edge has been rotated towards us while the backwards edge has been rotated away.

Let's now rotate the square by -45 degrees:

div {
   width: 100px;
   height: 100px;
   background-color: blue;
transform: perspective(500px) rotateY(-45deg); }

Rotation in the z-axis

We have the rotateZ() transform function to perform the exact same thing as rotate().

Needless to say, syntactically it's the same as rotate():

rotateY(<angle> | <zero>)

Let's try experimenting with this function.

As always, here's our initial configuration of a <div>, styled as a square:

And here it is after rotating it around the z-axis by 45 degrees:

div {
   width: 100px;
   height: 100px;
   background-color: blue;
transform: perspective(500px) rotateZ(45deg); }

Notice that rotateZ() is identical to rotate(), as demonstrated below:

div {
   width: 100px;
   height: 100px;
   background-color: blue;
transform: perspective(500px) rotate(45deg); }

Rotation in an arbitrary axis

Let's say we want to rotate an element freely in an arbitrary axis, for e.g. the diagonal axis in the xy plane, running from the top-left to the bottom-right.

You might think that this is easy and that we can directly work with the individual rotation functions rotateX(), rotateY() and rotateZ() to do so.

However, the scenario isn't that simple!

Yes, technically, we could use rotateX(), rotateY() and rotateZ(), but then for every degree of rotation in that axis, the rotation angles for each of these functions would most probably be quite different. To perform the correct rotation, we'll need to compute the angles ourselves.

A more flexible and simple way is what we need.

If you're familiar with vectors from mathematics, you'll be able to relate to the fact that 3D rotation transformations have two components to them: a rotation axis and a rotation angle.

The rotation axis is the axis around which the rotation occurs. It can be the x-axis, the y-axis, the z-axis, or just about any other axis, for e.g. the diagonal axis in the xy plane (as we talked about earlier).

On the other hand, the rotation angle obviously specifies how much the object under consideration should be rotated and in which direction — clockwise (with a positive angle) or counter-clockwise (with a negative angle).

In CSS, the transform function rotate3d() rotates an element based on this very idea. It represents the rotation axis along with the rotation angle.

Here's its syntax:

rotate3d(x, y, z, alpha)

The first three arguments — x, y and z — represent a vector that denotes the direction of the rotation axis. The fourth argument, alpha, specifies the rotation angle.

The first three arguments are internally normalized, i.e. scaled down or up so as to sum up to 1.

The functions rotateX(), rotateY() and rotateZ() are merely shortcuts of rotate3d(). Here's how:

  • rotateX(angle) is a shortcut of rotate3d(1, 0, 0, angle).
  • rotateY(angle) is a shortcut of rotate3d(0, 1, 0, angle).
  • rotateZ(angle) is a shortcut of rotate3d(0, 0, 1, angle).

Keep in mind that the vector coordinates provided to rotate3d() (via its first three args) is based on the 3D coordinate model used in CSS, NOT the typical model used in mathematics.

That is, positive y values run downwards, positive x values run rightwards, and positive z values run forwards (towards the viewer).

Let's consider an example illustrating rotate3d().

As always, here's our square <div>:

With the help of rotate3d(), we'll now try to rotate this in the diagonal xy axis (that runs from the top-left to the bottom-right) by 45 deg:

div {
   width: 100px;
   height: 100px;
   background-color: blue;
transform: perspective(500px) rotate3d(1, 1, 0, 45deg); }

The vector that we have above is 1, 1, 0, and points in the direction between these two axes.