Skip to content

Animated CSS3 cube using 3D transforms

Update (28th Sept 2010): Cube updated to work with touch ges­tures and click and drag — 3D CSS cube II

Last week WebKit included the much antic­i­pated (at least on my part) 3D trans­forms in its lat­est nightly build, announced prac­ti­cally along­side the awe­some Snow Stack demo that pro­vides a 3D inter­face for brows­ing Flickr images (use left, right and space-bar). Today the Surfin Safari blog has updated with some more excit­ing demos, includ­ing “Mor­phin Power Cubes” and “Poster Cir­cle”. It is now pos­si­ble to cre­ate all sorts of crazy three-dimensional and ani­mated user inter­faces; the power comes largely in -webkit-perspective and a num­ber of updated transforms–adapted to incor­po­rate the Z axis.

Since work­ing on the 3D cube using 2D trans­forms back in April I’ve exper­i­mented with per­spec­tive to cre­ate some­thing more pow­er­ful, play­ing around with 3D trans­forms on the iPhone a few times (e.g. this early rotat­ing demo). Now I’ve got some­thing worth sharing.

A 3D cube can be cre­ated solely in CSS, with all six faces. Using JavaScript to detect key presses and update inline styles this cube can be intu­itively navigated.

Result

A 3D cube that rotates using the Up, Down, Left and Right arrow keys.
Sup­ported browsers: WebKit Nightly r46042+

3D cube interface using new WebKit transforms

How To

I’ll start with the markup, because it’s sim­ple. Each of the six cube faces is given a face class and another relat­ing to it’s num­ber. These six faces sit within a cube con­tainer, which sits in another wrap­per, each is necessary.

<div id="experiment">
	<div id="cube">
		<div class="face one">
			One face
		</div>
		<div class="face two">
			Up, down, left, right
		</div>
		<div class="face three">
			Lorem ipsum.
		</div>
		<div class="face four">
			New forms of navigation are fun.
		</div>
		<div class="face five">
			Rotating 3D cube
		</div>
		<div class="face six">
			More content
		</div>
	</div>
</div>

The outer wrap­per serves as a cam­era, on which you apply some per­spec­tive — appro­pri­ate 3D trans­for­ma­tions are then applied to descen­dants. -webkit-perspective defines the depth of the Z-plane and rel­a­tive sizes of ele­ments above and below it, -webkit-perspective-origin spec­i­fies the perspective’s ori­gin. View a per­spec­tive exam­ple (webkit​.org)

    #experiment {
      -webkit-perspective: 800;
      -webkit-perspective-origin: 50% 200px;
    }

The sec­ond con­tainer, the actual cube, has a spec­i­fied height, mar­gin, posi­tion, etc. as usual. The height and width are nec­es­sary to cre­ate some con­fines for the cube face trans­for­ma­tions — alter­na­tively the width defaults to 100% and the cube’s appear­ance would vary with win­dow width. -webkit-transition (doc­u­men­ta­tion) defines the ani­mated prop­erty, dura­tion and timing-function — we’re ani­mat­ing the 3d trans­for­ma­tion (via -webkit-transform) lin­early for two sec­onds. -webkit-transform-style deter­mines whether child ele­ments lie flat against their par­ent (“flat”) or remain in 3D space (“preserve-3d”).

    #cube {
      position: relative;
      margin: 0 auto;
      height: 400px;
      width: 400px;
      -webkit-transition: -webkit-transform 2s linear;
      -webkit-transform-style: preserve-3d;
    }

Using the .face class com­mon styles are applied to the six sides; col­or­ing, size, padding, etc. Impor­tantly they are each posi­tioned absolutely, rel­a­tive to the cube con­tainer. The back­ground rgba prop­erty is included to make the cube look pretty and transparent.

    .face {
      position: absolute;
      height: 360px;
      width: 360px;
      padding: 20px;
      background-color: rgba(50, 50, 50, 0.7);
    }

Each of the faces, one through six, needs to be rotated in 3D space to its cor­rect start­ing posi­tion. Using translateZ the ele­ments are brought 200px (half their width) off the Z-plane. Each of the faces must be at 90 degrees. Rotat­ing solely in the X plane posi­tions the top and bot­tom faces (one, six), before rotat­ing the last four faces in the Y plane, much like origami. The extra rotate on the sixth face rotates the con­tent in 2D space to cor­rect its orientation.

    #cube .one  {
      -webkit-transform: rotateX(90deg) translateZ(200px);
    }

    #cube .two {
      -webkit-transform: translateZ(200px);
    }

    #cube .three {
      -webkit-transform: rotateY(90deg) translateZ(200px);
    }

    #cube .four {
      -webkit-transform: rotateY(180deg) translateZ(200px);
    }

    #cube .five {
      -webkit-transform: rotateY(-90deg) translateZ(200px);
    }

    #cube .six {
      -webkit-transform: rotateX(-90deg) translateZ(200px) rotate(180deg);
    }

Our cube is now com­plete — but it doesn’t move! With a key­down event lis­tener we can incre­ment X and Y angles based on dif­fer­ent key presses, before apply­ing them as inline styles on the cube con­tainer. In com­bi­na­tion with the tran­si­tion effect on #cube, all six faces rotate in sync from their orig­i­nal posi­tion to the newly defined angle, cre­at­ing a seam­less 3D cube interface.

  	var xAngle = 0, yAngle = 0;
	document.addEventListener('keydown', function(e)
	{
		switch(e.keyCode)
		{

			case 37: // left
				yAngle -= 90;
				break;

			case 38: // up
				xAngle += 90;
				break;

			case 39: // right
				yAngle += 90;
				break;

			case 40: // down
				xAngle -= 90;
				break;
		};

		$('cube').style.webkitTransform = "rotateX("+xAngle+"deg) rotateY("+yAngle+"deg)";
	}, false);

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.

44 Comments

  1. Aimee Graham

    That is one of the most amaz­ing things I have seen in a while. Could this also be poten­tially moved by click­ing or hov­er­ing in a cer­tain area of the cube?

  2. ardianzzz

    Wow! amaz­ing!

  3. dioxyd

    I am not able to see the pre­view in any of my cur­rent browsers?

    Here they are:

    1– Firefox/3.6 (.NET CLR 3.5.30729)

    2– Inter­net Explorer 8.0.6001.18882

    I just see lit­tle Sonic animation.

  4. b

    :( soo sad. I can’t see the 3d effect…they are all stacked up. and I have the lat­est ver­sion of Fir­fox (3.6) on mac … am I miss­ing something?

  5. Rogers

    but not dis­play­ing i IE

  6. Chris

    All above who are using Fire­fox or IE, this doesn’t work. Those aren’t webkit-based browsers. Chrome and Safari are…

  7. omegared

    like — I am espe­cially excited about the pos­si­bil­i­ties of using this with the iphone for navigation

  8. eyesoo

    太强大啦。我顶!

  9. Vilic

    强大!
    Thx a lot!

  10. Mike

    sadly, this is not work­ing in the lat­est ver­sion of chromium

  11. damu

    wow! excit­ing stuff :)

  12. Tracy Hare

    Great writeup! Got my panorama cube with no prob­lem. Any idea how to get the point of view inside the box?

  13. Marc Drewello

    Its very nice but i have two ques­tions! add my @twitter i fol­low u “Plextron”

    Greetz Marc

  14. christopher scott

    This is a really good exam­ple of the var­i­ous webkit props… thanks for writ­ing this up.

  15. Oren

    nice arti­cle.
    using chrome 6.0.472 and it doesn’t show 3d but does rotate one side only.any idea why?

  16. R Khodjaev

    It works on Webkit nightly only.

  17. Tony

    Holy mack­erel, Paul. This is incred­i­ble. Thanks for shar­ing your knowledge.

  18. Oscar

    WOW! ; ) amazing.

  19. Jeffrey Jones

    any chance we can nav­i­gate using mouseover events like hover?

  20. Mike

    Ele­gant implementation!

  21. Matteo

    This is my sam­ple based on this code used for a slideshow of 5 slides, so based on a pen­tag­o­nal prism: http://​jsfid​dle​.net/​T​r8hK/

  22. Ryan

    It is pos­si­ble to do this with­out jQuery by chang­ing the bot­tom line to:

    document.getElementById(‘cube’).style.webkitTransform = “rotateX(“+xAngle+“deg) rotateY(“+yAngle+“deg)”;

  23. nameisbryan

    Beau­ti­ful work.

    Is any­one up to the chal­lenge of embed­ding hyper­links to dif­fer­ent sur­faces of the cube?

  24. Serba Blog

    Wow.…Great Job…amazing…!!!

  25. Frankie

    Huh? Fire­fox sup­ports CSS Trans­forms. If you’re writ­ing –webkit spe­cific CSS it’s not very fair to leave out the cor­re­spond­ing –moz code for Gecko browsers.

  26. Samson

    Looks like cur­rently it only works in safari.
    Fan­tas­tic CSS3 effects~~~

  27. Matt

    When­ever you write a demo using ven­dor pre­fixes, it’s often best to include the pre­fixes of all browser ven­dors and also the un-prefixed ver­sion. That way the demo works in all browsers that even­tu­ally sup­port the stan­dard. Your demo cur­rently doesn’t work in Mozilla Nightly builds since you only have the webkit pre­fix. :(

  28. frida

    How to iden­tify posi­tion in the cube and how to do interactivity?

    I mean that if i will develop cubic panorama viewer refer to this demo, fur­ther­more, how to add hotspot at cer­tain point and how to inter­act with the point?

  29. Shaun

    1)how to add hyper­links in the faces of the cube ?

    2)3d effect not work­ing in chrome, is some­thing can be done to make it work in chrome also

  30. Magnus

    I can’t make it move, even when i use the: document.getElementById(‘cube’).style.webkitTransform = “rotateX(“+xAngle+“deg) rotateY(“+yAngle+“deg)”; sen­tence. I’m run­ning Safari. What could be the problem?

  31. Ed Zee

    This is great. Love it!

  32. Joe Lambert

    Great arti­cle Paul! I noticed that your demo imple­men­ta­tion suf­fers from some incon­sis­ten­cies regard­ing how user input maps to the result­ing rota­tions after the cube has been rotated the first time.

    I’ve just com­pleted a sim­i­lar exper­i­ment (largely helped by this arti­cle) and imple­mented a more robust rota­tion tech­nique — thought you may be inter­ested: http://​blog​.joe​lam​bert​.co​.uk/​2​0​1​1​/​0​5​/​1​0​/​h​a​n​d​l​i​n​g​-​3​d​-​g​e​o​m​e​t​r​y​-​w​i​t​h​-​3​d​-​c​s​s​3​-​t​r​a​n​s​f​orms/

  33. mairead

    I can’t get the key­board events to work with either syn­tax. any­one man­aged to work that out? I’m using WebKit r87281

    superb effort. Am lov­ing your exam­ples, proper wiz­ard magic.

  34. Karthik

    Why it is not work­ing in chrome?

  35. Regnareb

    Don’t work in Opera, Chrome and Fire­fox with­out any rea­son. Please add sup­port for them.

  36. Oswald
  37. Adam

    If y’all can’t see it, it’s because you aren’t using a wor­thy browser. And let’s be hon­est, there’s really no rea­son left in the world why you shouldn’t be using Chrome 11 or FF 4. Sooooo, yeah.… go do that.

  38. Matt Quartermain

    Neat, but there are bugs:

    The line start­ing:
    $(‘cube’).style.webkitTransform =
    should instead be:
    $(‘#cube’)[0].style.webkitTransform =
    or it won’t go round

    You might also want to indi­cate, for noobs, that you need to include a jquery library.

  39. Pumano

    Cha­lassa
    try change in #exper­i­ment {
    –webkit-perspective: –1000;
    } /* it fix blur, but some ele­ments can’t be selected…but if i want have all ele­ments selec­table I must use pos­i­tive value in per­spec­tive, but that give blur (((((. I will search a solution.*/

  40. so exciting!

    This is how CSS3 Ren­ders ! Yay!

  41. Andreas Lagerkvist

    This is totally awe­some but work­ing on my own ver­sion I’m expe­ri­enc­ing trou­ble with z-index. I haven’t copied your code in every detail but I don’t under­stand why yours doesn’t suf­fer the same prob­lems. All my faces are drawn on top of each other with the last face on top and the first on the bot­tom. Any idea why that doesn’t hap­pen to your cube?

  42. Andreas Lagerkvist
  43. Willie Meier

    Paul thanks for a great article

    I’ve taken arti­cle as a basis and made a trans­par­ent 3d cube and have each face play a video.

    Works great in IE9, FF, Opera, Chrome and Safari.

    There is a bit of an issue with the bot­tom face which I can­not get just quite right and won­der IF pos­si­bly
    using trans­for­ma­tion Matrix would be the answer and per­haps more precise.

    Would you be will­ing to offer help in mak­ing it pos­si­ble for mak­ing the 3D trans­par­ent cube rotate using the ‘keypress’?

    thanks

  44. Staale

    Hi. I’m hav­ing trou­ble get­ting this to work. I’ve tried the var­i­ous tweaks in the com­ments. I’m get­ting: ” $(“cube”).style is unde­fined ” in the con­sole when I press the keys.
    I’m a bit new at this so I might be mak­ing some obvi­ous blun­der. My file is at http://​esdi​a​log​.no/​t​e​s​t​i​n​g​/​3​d​_​c​u​b​e​/​i​n​d​e​x​.html