Skip to content

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;
}

Paul Hayes Paul Hayes is a developer at Last.fm. You should follow him on Twitter, where he talks about UX, HTML, CSS and JavaScript, amongst other cool stuff.

31 Comments Post your own

  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. mostafa farghaly

    great work paul :)

  7. wavded

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

  8. Paul Hayes

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

  9. michel perrin

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

  10. Brent

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

  11. mupet

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

  12. 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.

  13. anonymous

    Where’s the Z axis then?

  14. 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.

  15. Jason Grant

    Inter­est­ing stuff.

  16. 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 …

  17. 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.

  18. Roberto

    Inter­est­ing. Thanks for sharing.

  19. woitekk

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

  20. Lauren

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

  21. anil

    not work­ing in FF also IE7

  22. 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.

  23. NabZ

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

  24. Deko web tasarım

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

  25. ahkeno

    Awe­some.. Love CSS… thank for sharing

  26. Srinivas Kothuri

    Hi, very nice tuto­r­ial. I tried to set bor­der for the divi­sion which forms the cube’s top. The bor­der is not prop­erly aligned on for that divi­sion. Below is what I tried.

    Plz. clar­ify me on this…Thank you

  27. Anonymous

    On the demo page, you said “take a peak at the CSS”. It’s “peek”, not “peak”. A peak is the top of a moun­tain. A peek is a look.

  28. hoowolf

    It’s cool! Good Job!非常不错啊!

  29. Mansoor Khan

    Good job Paul! Let’s hope we get sup­port on other browsers soon.

  30. 027health

    very good!!!www.027health.com

  31. jack

    cool