In the third part of this series it seems appropriate to discuss three-dimensional transformations.
As you’d expect, 3D is more complex and slightly less stable in browsers. To ensure reasonable compatibility:
- Use the standard and -webkit- prefixed versions of all properties (these are not shown in the code samples below but are in the demonstrations).
- Forget IE9 and below. 3D transformations are supported in IE10 but the browser is missing a key property and you may need to adapt code for full cross-browser support (more about that later).
3D on a 2D Screen?
In two dimensions, we have a horizontal x-axis and vertical y-axis. In three dimensions, we also have a z-axis. If you assume your screen is z co-ordinate zero, a positive value moves an object toward you and a negative value moves it away from you into the screen. Add some perspective and an object may disappear into the distance.
There are some other points you should note which are specific to browsers:
- We’re transforming two dimensional elements in 3D space. HTML boxes remain flat and have zero depth. Even though you can scale an element in z-plane, it won’t extrude — i.e. your circle will remain a circle and won’t become a cylinder.
- A 3D transformation is applied to all inner elements.
- It’s a little too easy to transform an element so it’s moved behind you or off the screen in some way! My recommendation: test often and undo any catastrophic transformations.
Applying Depth
We’ll start with a simple example:
<div id="stage">
<div id="mybox1">BOX 1</div>
<div id="mybox2">BOX 2</div>
<div id="mybox3">BOX 3</div>
</div>
Our outer element (#stage) contains three boxes colored a transparent red, green and blue respectively. The outer element isn’t strictly required but it will allow us to rotate the whole scene which helps with visualization.
First, we’ll attempt to move boxes two and three further back into the screen using the translateZ
function which is identical to translateX
and translateY
except it applies to depth:
#mybox2
{
transform: translateZ(-300px);
}
#mybox3
{
transform: translateZ(-600px);
}
View the first 3D transformation demonstration page…
The result:
That’s not what we expected; BOX 3 is certainly above the others. The reason is the transform-style
property which has a default value of flat
. This applies all 3D transformations in the same two dimensional plane so, while transforms occur, there is no illusion of depth. To fix this, we need to apply a value of preserve-3d
to our outer #stage container:
#stage
{
transform-style: preserve-3d;
}
View the second 3D transformation demonstration page…
IE10 is Flat!
Unfortunately, IE10 does not support transform-style
so BOX 3 will remain above BOX 1. All is not lost since we can apply 3D transformations to individual elements. However, it’s not possible to apply effects to a container with multiple child elements so the following demonstrations will not work in the browser. Let’s hope Microsoft address the issue in IE11.
So, IE10 apart, we’re getting closer but there’s no illusion of depth. Let’s…
Get Some Perspective
In the demonstration above we’re sitting at the front of the stage looking at our three boxes. But there’s no perspective so BOX 1 is exactly the same size as BOX 2 and BOX 3. We can illustrate this by moving the whole outer #stage:
#stage
{
transform: rotateX(-20deg) rotateY(-40deg);
}
We’re now sitting on the right side of the the theater looking at our stage with the three boxes:
The perspective
transform function will ensure objects which are further away become smaller:
#stage
{
transform: rotateX(-20deg) rotateY(-40deg) perspective(600px);
}
View the third 3D transformation demonstration page…
The perspective
function is passed a single value which indicates how close the viewer is to the action. The lower the number, the more pronounced the perspective effect. Think of 0px as sitting on the front row of the #stage; it’s easier to see the relative distances between actors and objects. A value of 1000px would be the back of the upper circle; it’s more difficult to judge accurate distances so the objects appear to be a similar size.
Try using your own #stage rotation and perspective values to see how it affects the elements. In the next lesson, we’ll apply other transform
functions to our 3D scene.
Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.