Update (28th Sept 2010): Cube updated to work with touch gestures and click and drag — 3D CSS cube II
Last week WebKit included the much anticipated (at least on my part) 3D transforms in its latest nightly build, announced practically alongside the awesome Snow Stack demo that provides a 3D interface for browsing Flickr images (use left, right and space-bar). Today the Surfin Safari blog has updated with some more exciting demos, including “Morphin Power Cubes” and “Poster Circle”. It is now possible to create all sorts of crazy three-dimensional and animated user interfaces; the power comes largely in -webkit-perspective and a number of updated transforms–adapted to incorporate the Z axis.
Since working on the 3D cube using 2D transforms back in April I’ve experimented with perspective to create something more powerful, playing around with 3D transforms on the iPhone a few times (e.g. this early rotating demo). Now I’ve got something worth sharing.
A 3D cube can be created solely in CSS, with all six faces. Using JavaScript to detect key presses and update inline styles this cube can be intuitively navigated.
Result
A 3D cube that rotates using the Up, Down, Left and Right arrow keys.
Supported browsers: WebKit Nightly r46042+

How To
I’ll start with the markup, because it’s simple. Each of the six cube faces is given a face class and another relating to it’s number. These six faces sit within a cube container, which sits in another wrapper, 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 wrapper serves as a camera, on which you apply some perspective — appropriate 3D transformations are then applied to descendants. -webkit-perspective defines the depth of the Z-plane and relative sizes of elements above and below it, -webkit-perspective-origin specifies the perspective’s origin. View a perspective example (webkit.org)
#experiment {
-webkit-perspective: 800;
-webkit-perspective-origin: 50% 200px;
}
The second container, the actual cube, has a specified height, margin, position, etc. as usual. The height and width are necessary to create some confines for the cube face transformations — alternatively the width defaults to 100% and the cube’s appearance would vary with window width. -webkit-transition (documentation) defines the animated property, duration and timing-function — we’re animating the 3d transformation (via -webkit-transform) linearly for two seconds. -webkit-transform-style determines whether child elements lie flat against their parent (“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 common styles are applied to the six sides; coloring, size, padding, etc. Importantly they are each positioned absolutely, relative to the cube container. The background rgba property 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 correct starting position. Using translateZ the elements are brought 200px (half their width) off the Z-plane. Each of the faces must be at 90 degrees. Rotating solely in the X plane positions the top and bottom faces (one, six), before rotating the last four faces in the Y plane, much like origami. The extra rotate on the sixth face rotates the content in 2D space to correct 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 complete — but it doesn’t move! With a keydown event listener we can increment X and Y angles based on different key presses, before applying them as inline styles on the cube container. In combination with the transition effect on #cube, all six faces rotate in sync from their original position to the newly defined angle, creating a seamless 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);
44 Comments
That is one of the most amazing things I have seen in a while. Could this also be potentially moved by clicking or hovering in a certain area of the cube?
Wow! amazing!
I am not able to see the preview in any of my current browsers?
Here they are:
1– Firefox/3.6 (.NET CLR 3.5.30729)
2– Internet Explorer 8.0.6001.18882
I just see little Sonic animation.
but not displaying i IE
All above who are using Firefox or IE, this doesn’t work. Those aren’t webkit-based browsers. Chrome and Safari are…
like — I am especially excited about the possibilities of using this with the iphone for navigation
太强大啦。我顶!
强大!
Thx a lot!
sadly, this is not working in the latest version of chromium
wow! exciting stuff
Great writeup! Got my panorama cube with no problem. Any idea how to get the point of view inside the box?
Its very nice but i have two questions! add my @twitter i follow u “Plextron”
Greetz Marc
This is a really good example of the various webkit props… thanks for writing this up.
nice article.
using chrome 6.0.472 and it doesn’t show 3d but does rotate one side only.any idea why?
It works on Webkit nightly only.
Holy mackerel, Paul. This is incredible. Thanks for sharing your knowledge.
WOW! ; ) amazing.
any chance we can navigate using mouseover events like hover?
Elegant implementation!
This is my sample based on this code used for a slideshow of 5 slides, so based on a pentagonal prism: http://jsfiddle.net/Tr8hK/
It is possible to do this without jQuery by changing the bottom line to:
document.getElementById(‘cube’).style.webkitTransform = “rotateX(“+xAngle+“deg) rotateY(“+yAngle+“deg)”;
Beautiful work.
Is anyone up to the challenge of embedding hyperlinks to different surfaces of the cube?
Wow.…Great Job…amazing…!!!
Huh? Firefox supports CSS Transforms. If you’re writing –webkit specific CSS it’s not very fair to leave out the corresponding –moz code for Gecko browsers.
Looks like currently it only works in safari.
Fantastic CSS3 effects~~~
Whenever you write a demo using vendor prefixes, it’s often best to include the prefixes of all browser vendors and also the un-prefixed version. That way the demo works in all browsers that eventually support the standard. Your demo currently doesn’t work in Mozilla Nightly builds since you only have the webkit prefix.
How to identify position in the cube and how to do interactivity?
I mean that if i will develop cubic panorama viewer refer to this demo, furthermore, how to add hotspot at certain point and how to interact with the point?
1)how to add hyperlinks in the faces of the cube ?
2)3d effect not working in chrome, is something can be done to make it work in chrome also
I can’t make it move, even when i use the: document.getElementById(‘cube’).style.webkitTransform = “rotateX(“+xAngle+“deg) rotateY(“+yAngle+“deg)”; sentence. I’m running Safari. What could be the problem?
This is great. Love it!
Great article Paul! I noticed that your demo implementation suffers from some inconsistencies regarding how user input maps to the resulting rotations after the cube has been rotated the first time.
I’ve just completed a similar experiment (largely helped by this article) and implemented a more robust rotation technique — thought you may be interested: http://blog.joelambert.co.uk/2011/05/10/handling-3d-geometry-with-3d-css3-transforms/
I can’t get the keyboard events to work with either syntax. anyone managed to work that out? I’m using WebKit r87281
superb effort. Am loving your examples, proper wizard magic.
Why it is not working in chrome?
Don’t work in Opera, Chrome and Firefox without any reason. Please add support for them.
CSS3 2D/3D/Animation code samples (no JS):
http://code.google.com/p/css3-graphics/
Oswald
If y’all can’t see it, it’s because you aren’t using a worthy browser. And let’s be honest, there’s really no reason left in the world why you shouldn’t be using Chrome 11 or FF 4. Sooooo, yeah.… go do that.
Neat, but there are bugs:
The line starting:
$(‘cube’).style.webkitTransform =
should instead be:
$(‘#cube’)[0].style.webkitTransform =
or it won’t go round
You might also want to indicate, for noobs, that you need to include a jquery library.
Chalassa
try change in #experiment {
–webkit-perspective: –1000;
} /* it fix blur, but some elements can’t be selected…but if i want have all elements selectable I must use positive value in perspective, but that give blur (((((. I will search a solution.*/
This is how CSS3 Renders ! Yay!
This is totally awesome but working on my own version I’m experiencing trouble with z-index. I haven’t copied your code in every detail but I don’t understand why yours doesn’t suffer the same problems. All my faces are drawn on top of each other with the last face on top and the first on the bottom. Any idea why that doesn’t happen to your cube?
I don’t know how or when but it started working
Results here: http://exscale.se/__files/uploads/jquery-3d-circle.htm
Paul thanks for a great article
I’ve taken article as a basis and made a transparent 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 bottom face which I cannot get just quite right and wonder IF possibly
using transformation Matrix would be the answer and perhaps more precise.
Would you be willing to offer help in making it possible for making the 3D transparent cube rotate using the ‘keypress’?
thanks
Hi. I’m having trouble getting this to work. I’ve tried the various tweaks in the comments. I’m getting: ” $(“cube”).style is undefined ” in the console when I press the keys.
I’m a bit new at this so I might be making some obvious blunder. My file is at http://esdialog.no/testing/3d_cube/index.html