3D Cube using 2D CSS transformations

Update (July 21st): Using newly released (cur­rently only in Webkit Nightly releases) 3D trans­forms, a three dimen­sional, rotat­ing cube with cor­rect per­spec­tive is pos­si­ble, and as a bonus–the cube can be nav­i­gated using arrow keys. Check out the lat­est demo, “Ani­mated CSS3 cube using 3D trans­forms”.

The impres­sion of a three dimen­sional cube can be cre­ated using mod­ern CSS tech­niques, with­out the need for JavaScript, imagery, can­vas or SVG. Using the pro­pri­etary trans­form prop­erty to skew and rotate shaded rec­tan­gles, indi­vid­ual cube faces can com­bine to form a 3D object. Cur­rently only sup­ported in recent WebKit and Gecko based browsers, most impor­tantly Fire­fox 3.5+ -moz-transform (doc­u­men­ta­tion) and Safari 3.2+ -webkit-transform (doc­u­men­ta­tion).

To demon­strate the power of this effect a sec­ond exper­i­ment with mul­ti­ple cubes and pro­pri­etary WebKit tran­si­tions is also available.

Results

A 3D cube cre­ated with CSS
Update (June 7th): Altered CSS slightly to use skew(x,y) rather than skewY, the lat­ter of which is not sup­ported in Safari 3 / Chrome.
Sup­ported browsers: Safari 3.2+, Google Chrome, Fire­fox 3.5+

Exper­i­ment with mul­ti­ple cubes and CSS tran­si­tions, still no JavaScript
Sup­ported browsers: Safari 4+, Google Chrome

Multiple cubes created using CSS

How To

Sim­i­lar to my pre­vi­ous exper­i­ments, the HTML markup is very sim­ple. Each of the faces has its own DIV, class and con­tent. The top face requires some extra markup to aid the trans­for­ma­tion, 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 dis­claimer, the geom­e­try in this exam­ple is ‘fudged’, in that the val­ues have been adjusted to appear roughly cor­rect. I know that the dimen­sions are slightly out of whack, this is merely to save my head from math­e­mat­ics and to get the con­cept out there quickly for peo­ple to see. With that said, let’s crack on with the CSS.

Each of the three rec­tan­gles is given a slightly dif­fer­ent shade of gray to give the impres­sion of depth, in this exam­ple the left face is in shadow. The faces are each posi­tioned absolutely, rel­a­tive to the cube con­tainer. Each face is 200 x 200 pix­els, includ­ing 10 pix­els 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 rec­tan­gles are skewed by ±30˚ along the ver­ti­cal axis, with the right face shifted left by 200px, cleanly lin­ing up the two edges to cre­ate a cor­ner that is cen­ter 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 prob­lem­atic; it needs to be skewed, scaled, rotated and posi­tioned. The skew is the same, –30˚ along the ver­ti­cal axis, this skewed rec­tan­gle must then be rotated clock­wise by 60˚. Rotat­ing the rec­tan­gle itself leads to a change in ori­en­ta­tion of its con­tent, a con­tainer must be added and then rotated.

A sim­ple way of cre­at­ing a top face with­out resort­ing to maths is to dupli­cate the left and right rec­tan­gles, skew them in the oppo­site direc­tions (by invert­ing the sign, e.g. left face is now skewed by –30˚) and posi­tion them against the exist­ing faces to cre­ate a dia­mond shape between the two sets. Now use posi­tion­ing and scal­ing to fill this dia­mond and form the top face, delet­ing the dupli­cates when fin­ished. My results led to a scal­ing fac­tor of 1.16 in the Y direc­tion which I have accounted for by reduc­ing 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;
}

29 Comments

  1. Paul Bakaus

    Nice one! I did the very same for a demo last year, but with a sin­gle back­ground tex­ture that gets pro­jected on the cube (this is cool for online games).

    Also, you might con­sider scal­ing down the outer box again so the size will be equal to the orig­i­nal size.

  2. Pedro Rogério

    I am with­out words for this tuto­r­ial. Congratulations.

  3. Kasi

    Hello, very cool.

    so, wie can nice cre­ate nice Web­de­signs in the future, but now ist music for tomorrow.

    Best regards from ger­many
    Kasi

  4. Mahmud Ahsan

    Awe­some

  5. Rodney Reid

    Wow very nice Paul — you are a CSS god :)

  6. 墨尔本

    Very cool fea­ture!
    Thanks for sharing.

  7. mostafa farghaly

    great work paul :)

  8. wavded

    Your sec­ond demo seems to work OK on Fire­fox 3.5 Beta 4. Unless I’m miss­ing something.

  9. Paul Hayes

    The ani­ma­tion which moves the boxes in and out on hover will not work in FF3.5

  10. michel perrin

    Curi­ously, the first demo doesn’t work in my safari V3.2.1

  11. Brent

    Super cool. Thank you for the tuto­r­ial and excel­lent work !

  12. mupet

    Amaz­ing, i dont think we can do this using css before

  13. flash tekkie

    Very nice job on this one! Let’s hope trans­forms will be there in the released W3C stan­dard at some point.

  14. anonymous

    Where’s the Z axis then?

  15. RaBBi

    Like michel per­rin, the first demo doesn’t work in last updated Safari 3.2.3 ^^
    Only the top­face cube is skewed.

  16. art2code

    excel­lent!
    thx

  17. Jason Grant

    Inter­est­ing stuff.

  18. aimee.mychores.co.uk

    Now if it could just take per­spec­tive into account, then i would be REALLY impressed.

    For me this is cur­rently look­ing more like ‘gim­mick’ than ‘use­ful fea­ture’. We shall se …

  19. Ken

    Nifty!

    FWIW: the first exam­ple, which says it works in Chrome, doesn’t work in Chrome here. But the sec­ond one does.

  20. Roberto

    Inter­est­ing. Thanks for sharing.

  21. Uwa Semar

    Wow nice info,…

  22. woitekk

    This is truly beau­ti­ful. Thank You for that post. Big up.

  23. Lauren

    The faulty per­spec­tive bugs me but it’s still amazing!

  24. Vesa Virlander

    Good job with this!

  25. anil

    not work­ing in FF also IE7

  26. Zoltan Hawryluk

    Excel­lent arti­cle — espe­cially love your cube exam­ples. I hope you don’t mind, but I used your design idea in my arti­cle about “Cross Browser CSS Trans­forms – even in IE” (http://​www​.user​a​gent​man​.com/​b​l​o​g​/​2​0​1​0​/​0​3​/​0​9​/​c​r​o​s​s​-​b​r​o​w​s​e​r​-​c​s​s​-​t​r​a​n​s​f​o​r​m​s​-​e​v​e​n​-​i​n-ie/). It looks great in Explorer as well.

  27. NabZ

    Won­der­ful job bro… I am speach­less.… thanks a ton.

  28. Deko web tasarım

    really nice arti­cle and tuto­r­ial, thanks for sharing…

  29. ahkeno

    Awe­some.. Love CSS… thank for sharing