Update (July 21st): Using newly released (currently only in Webkit Nightly releases) 3D transforms, a three dimensional, rotating cube with correct perspective is possible, and as a bonus–the cube can be navigated using arrow keys. Check out the latest demo, “Animated CSS3 cube using 3D transforms”.
The impression of a three dimensional cube can be created using modern CSS techniques, without the need for JavaScript, imagery, canvas or SVG. Using the proprietary transform property to skew and rotate shaded rectangles, individual cube faces can combine to form a 3D object. Currently only supported in recent WebKit and Gecko based browsers, most importantly Firefox 3.5+ -moz-transform (documentation) and Safari 3.2+ -webkit-transform (documentation).
To demonstrate the power of this effect a second experiment with multiple cubes and proprietary WebKit transitions is also available.
Results
A 3D cube created with CSS
Update (June 7th): Altered CSS slightly to use skew(x,y) rather than skewY, the latter of which is not supported in Safari 3 / Chrome.
Supported browsers: Safari 3.2+, Google Chrome, Firefox 3.5+
Experiment with multiple cubes and CSS transitions, still no JavaScript
Supported browsers: Safari 4+, Google Chrome
How To
Similar to my previous experiments, the HTML markup is very simple. Each of the faces has its own DIV, class and content. The top face requires some extra markup to aid the transformation, more on that shortly.
<div class="cube"> <div class="topFace"> <div> Content </div> </div> <div class="leftFace"> Content </div> <div class="rightFace"> Content </div> </div>
A short disclaimer, the geometry in this example is ‘fudged’, in that the values have been adjusted to appear roughly correct. I know that the dimensions are slightly out of whack, this is merely to save my head from mathematics and to get the concept out there quickly for people to see. With that said, let’s crack on with the CSS.
Each of the three rectangles is given a slightly different shade of gray to give the impression of depth, in this example the left face is in shadow. The faces are each positioned absolutely, relative to the cube container. Each face is 200 x 200 pixels, including 10 pixels of padding.
.cube {
position: relative;
top: 200px;
}
.rightFace,
.leftFace,
.topFace div {
padding: 10px;
width: 180px;
height: 180px;
}
.rightFace,
.leftFace,
.topFace {
position: absolute;
}
Now for the fun bit. The left and right rectangles are skewed by ±30˚ along the vertical axis, with the right face shifted left by 200px, cleanly lining up the two edges to create a corner that is center aligned.
.leftFace {
-webkit-transform: skewY(30deg);
-moz-transform: skewY(30deg);
background-color: #ccc;
}
.rightFace {
-webkit-transform: skewY(-30deg);
-moz-transform: skewY(-30deg);
background-color: #ddd;
left: 200px;
}
The top face proves more problematic; it needs to be skewed, scaled, rotated and positioned. The skew is the same, –30˚ along the vertical axis, this skewed rectangle must then be rotated clockwise by 60˚. Rotating the rectangle itself leads to a change in orientation of its content, a container must be added and then rotated.
A simple way of creating a top face without resorting to maths is to duplicate the left and right rectangles, skew them in the opposite directions (by inverting the sign, e.g. left face is now skewed by –30˚) and position them against the existing faces to create a diamond shape between the two sets. Now use positioning and scaling to fill this diamond and form the top face, deleting the duplicates when finished. My results led to a scaling factor of 1.16 in the Y direction which I have accounted for by reducing the font-size by the same factor.
.topFace div {
-webkit-transform: skewY(-30deg) scaleY(1.16);
-moz-transform: skewY(-30deg) scaleY(1.16);
background-color: #eee;
font-size: 0.862em;
}
.topFace {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
top: -158px;
left: 100px;
}
The final CSS looks like this:
.cube {
position: relative;
top: 200px;
}
.rightFace,
.leftFace,
.topFace div {
padding: 10px;
width: 180px;
height: 180px;
}
.rightFace,
.leftFace,
.topFace {
position: absolute;
}
.leftFace {
-webkit-transform: skewY(30deg);
-moz-transform: skewY(30deg);
background-color: #ccc;
}
.rightFace {
-webkit-transform: skewY(-30deg);
-moz-transform: skewY(-30deg);
background-color: #ddd;
left: 200px;
}
.topFace div {
-webkit-transform: skewY(-30deg) scaleY(1.16);
-moz-transform: skewY(-30deg) scaleY(1.16);
background-color: #eee;
font-size: 0.862em;
}
.topFace {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
top: -158px;
left: 100px;
}

31 Comments Post your own
Nice one! I did the very same for a demo last year, but with a single background texture that gets projected on the cube (this is cool for online games).
Also, you might consider scaling down the outer box again so the size will be equal to the original size.
I am without words for this tutorial. Congratulations.
Hello, very cool.
so, wie can nice create nice Webdesigns in the future, but now ist music for tomorrow.
Best regards from germany
Kasi
Awesome
Wow very nice Paul — you are a CSS god
great work paul
Your second demo seems to work OK on Firefox 3.5 Beta 4. Unless I’m missing something.
The animation which moves the boxes in and out on hover will not work in FF3.5
Curiously, the first demo doesn’t work in my safari V3.2.1
Super cool. Thank you for the tutorial and excellent work !
Amazing, i dont think we can do this using css before
Very nice job on this one! Let’s hope transforms will be there in the released W3C standard at some point.
Where’s the Z axis then?
Like michel perrin, the first demo doesn’t work in last updated Safari 3.2.3 ^^
Only the topface cube is skewed.
Interesting stuff.
Now if it could just take perspective into account, then i would be REALLY impressed.
For me this is currently looking more like ‘gimmick’ than ‘useful feature’. We shall se …
Nifty!
FWIW: the first example, which says it works in Chrome, doesn’t work in Chrome here. But the second one does.
Interesting. Thanks for sharing.
This is truly beautiful. Thank You for that post. Big up.
The faulty perspective bugs me but it’s still amazing!
not working in FF also IE7
Excellent article — especially love your cube examples. I hope you don’t mind, but I used your design idea in my article about “Cross Browser CSS Transforms – even in IE” (http://www.useragentman.com/blog/2010/03/09/cross-browser-css-transforms-even-in-ie/). It looks great in Explorer as well.
Wonderful job bro… I am speachless.… thanks a ton.
really nice article and tutorial, thanks for sharing…
Awesome.. Love CSS… thank for sharing
Hi, very nice tutorial. I tried to set border for the division which forms the cube’s top. The border is not properly aligned on for that division. Below is what I tried.
Plz. clarify me on this…Thank you
On the demo page, you said “take a peak at the CSS”. It’s “peek”, not “peak”. A peak is the top of a mountain. A peek is a look.
It’s cool! Good Job!非常不错啊!
Good job Paul! Let’s hope we get support on other browsers soon.
very good!!!www.027health.com
cool