Skip to content

CSS 3D Transitions: An Introduction


On the web there are already several solutions for 3D capability: Flash; three.js in ; and, eventually, WebGL. Also, front-end developers have our own three-dimensional tool: CSS 3-D transforms.


Just like the 2d transition module released by Apple in Safari, 3D transitions initially were only supported by Safari. Since the release all of the major browsers, and IE10, everything either partially or fully supports 3D transitions. Take a look at the most up-to-date compatibility chart.

Compatibility Chart

Please keep in mind that you still need to use Modernizr to ensure that you are not throwing errors on browsers that do not support this particular module. However, it is the best way to test for CSS 3-D transform support and any other modules.

Getting Started

The way the 3D transforms work is that there is a DOM element that sets the perspective reference, and elements that are to be rendered using 3D transforms are contained within this element. The reference element is not a viewport in the sense of typical 3D applications. Think of it more along the lines of the world scene graph. Elements are allowed to be outside of this container as is the case normally with CSS positioning using a negative offset or margin. There are other ways that content may appear outside of the parent element using 3D transforms as well.

In case this is your first experience with CSS3D, we are going to jump right into cubes. Lets lay the framework for the HTML:


<pre class="language-html">[code] <code></code></pre>

<span>1 2 3 4 5 6</span>


Basic position and size styles set the 6 faces on top of one another in the container. CSS:

[code] <code>.container { width: 200px; height: 200px; position: relative; perspective: 1000px; } #cube { width: 100%; height: 100%; position: absolute; transform-style: preserve-3d; } #cube figure { width: 196px; height: 196px; display: block; position: absolute; border: 2px solid black; } [/code] </code>

The cube requires that 5 of the 6 faces to be rotated. Faces 1 and 2 will be the front and back. Faces 3 and 4 will be the sides. Faces 5 and 6 will be the top and bottom.

[code] #cube .front { transform: rotateY( 0deg ) translateZ( 100px ); } #cube .back { transform: rotateX( 180deg ) translateZ( 100px ); } #cube .right { transform: rotateY( 90deg ) translateZ( 100px ); } #cube .left { transform: rotateY( -90deg ) translateZ( 100px ); } #cube .top { transform: rotateX( 90deg ) translateZ( 100px ); } #cube .bottom { transform: rotateX( -90deg ) translateZ( 100px ); } [/code] 

Now each face is rotated, and only the front face is visible. The 4 side faces are all perpendicular to the viewer so they will appear invisible. To push them out to their appropriate sides they need to be translated out from the center of their positions. Each side of the cube is 200px wide, from the cube's center they'll need to be translated out half that distance which is 100px.

Note here that the translateZ function comes after the rotate. The order of transform functions is important. Take a moment and soak this in. Each face is first rotated towards its position, then translated outward in a separate vector. It's important to keep this in mind. You should now have a working cube, but we are not quite finished.

In order to keep 3D transforms snappy, Safari composites the element and then applies the transform. Consequently, anti-aliasing on text will remain whatever it was before the transform was applied. When transformed forward in 3D space, significant pixelation can and will occur, be cautious with this.

To expose any face of the cube, we'll need a style that rotates the cube to expose any face. The transform is the opposite of the corresponding face. We toggle the necessary class on the #box to apply the appropriate transform.

[code] { transform: translateZ( -100px ) rotateY( 0deg ); } { transform: translateZ( -100px ) rotateX( -180deg ); } { transform: translateZ( -100px ) rotateY( -90deg ); } { transform: translateZ( -100px ) rotateY( 90deg ); } { transform: translateZ( -100px ) rotateX( -90deg ); } { transform: translateZ( -100px ) rotateX( 90deg ); } [/code] 

Notice how the order of the transform functions have reversed. First we push the object back with translateZ, then we rotate it.

Finishing up, we can add a transition to animate the rotation between states.

[code] #cube { transition: transform 1s; } [/code] 

Below you can find a fully working example with some buttons added in to switch between each side of the cube: Cube Demonstration

Blog & Events

Featured Work