CSS 3D cube with touch gestures, click and drag

Exper­i­ment: 3D cube with touch ges­tures and click and drag

3D cube

An update on the orig­i­nal 3D cube (from July 2009 no less), I’ve added touch ges­ture sup­port (iOS) and click-and-drag behav­iour. Ani­ma­tion is incred­i­bly smooth on the iPhone, even the 3G model. Arrow key presses will still rotate the cube, and ESC will reset it.

One year on and the cube still only works in Safari. Chrome, which says it sup­ports webkit-perspective and webkit-transform, still ren­ders dif­fer­ently. Fire­fox doesn’t sup­port 3D trans­forms yet.

Exper­i­ment updated for Fire­fox 10 which sup­ports 3D trans­forms. Although the per­spec­tive appears off, prob­a­bly due to a perspective-origin bug.

It works rel­a­tively sim­ply: on click the start co-ordinates are saved and on drag the dif­fer­ence between cur­rent drag posi­tion and start­ing co-ordinates are applied to the cube as a trans­form, which is com­pleted after the spec­i­fied tran­si­tion dura­tion. Many thanks to Remy Sharp and his rubik’s exper­i­ment, which got me started with a lot of the basics.

Touch tweaks

Pixel val­ues for touch posi­tions are found in event.originalEvent.touches[0].pageX, instead of event.pageX. Using ‘start minus cur­rent’ pixel val­ues led the cube to rotate more than intended on the iPhone. To cor­rect, and for intu­itive behav­iour, the dif­fer­ence is reduced by a fac­tor of four.

JavaScript pre­vents sin­gle touch default events — e.g. scrolling and text selec­tion, but if it detects more than one touch (event.originalEvent.touches.length) the cube won’t rotate, so pinch and zoom will still work. This is a compromise.

A 200ms tran­si­tion dura­tion suits the browser, but on touch devices it felt slug­gish, so I’ve upped it to 50ms so the cube is always at your finger-tips.

Bet­ter CSS

The cube is cre­ated exactly as before, but I’ve sim­pli­fied the markup a lit­tle — drop­ping the face and num­ber class names in favour of CSS3 selectors:

#cube > div:first-child  {
-webkit-transform: rotateX(90deg) translateZ(200px);
-moz-transform: rotateX(90deg) translateZ(200px);
}

#cube > div:nth-child(2) {
-webkit-transform: translateZ(200px);
-moz-transform: translateZ(200px);
}

#cube > div:nth-child(3) {
-webkit-transform: rotateY(90deg) translateZ(200px);
-moz-transform: rotateY(90deg) translateZ(200px);
text-align: center;
}

#cube > div:nth-child(4) {
-webkit-transform: rotateY(180deg) translateZ(200px);
-moz-transform: rotateY(180deg) translateZ(200px);
}

#cube > div:nth-child(5) {
-webkit-transform: rotateY(-90deg) translateZ(200px);
-moz-transform: rotateY(-90deg) translateZ(200px);
}

#cube > div:nth-child(6) {
-webkit-transform: rotateX(-90deg) rotate(180deg) translateZ(200px);
-moz-transform: rotateX(-90deg) rotate(180deg) translateZ(200px);
}

Any ques­tions?

This is quite a speedy write-up, if any­thing needs explain­ing I’m happy to go into a bit more detail.

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.

20 Comments

  1. André Hartman

    I was impressed by your orig­i­nal cube and I am work­ing on inte­grat­ing this in an iPhone-only web site that I did for myself to track stock options. Now this is sin­gle series only and I want to use the cube to be able to present mul­ti­ple series each on a cube face.

    The orig­i­nal 3D exam­ple has all JS and CSS in line in the HTML. That makes it easy to study and use and adapt. The new exam­ple with touch ges­tures refers to Javascript and CSS files that are not avail­able for the user. That makes it much harder to see how it works.

    So, if you have time, please re-organize your lat­est exam­ple. And keep up the good work.
    Kind regards, André Hart­man, Belgium.

  2. grayson

    Hey, it’s hard to fig­ure out how to use this code myself. Do you not post source files? There are some ref­er­ences in the code that you don’t talk about :(

  3. Francesco

    Any chances to see youtube videos face on the i-phone?

  4. Paul Hayes

    View source on the exper­i­ment will reveal all. I’ve also put links to the CSS and JS at the top of the exper­i­ment page.

  5. dylanevl

    I’ve tried to get this to work in both Chromium 8.0.552.215 and the 11.00 beta ver­sion of Opera but to no avail. (I’m on an Ubuntu 8.04 box if that matters.)

    No cube, no rota­tions, just a square with an embed­ded video.

  6. B e n t o n

    Paul this is amaz­ing.
    I am alright with html & Css but I seem to be hav­ing real prob­lems get­ting the motion from the javascript.
    http://​john​ben​ton​.tv/​n​e​w​S​i​t​e​/​h​t​m​l​/​p​a​u​l​H​a​y​e​s​.html
    Thanks if you get a chance,
    I look for­ward to see­ing this Css 3D work­ing more.
    Thanks
    JB

  7. Benton

    Whoop. Got it!
    Thanks Paul, your work is inspi­ra­tional
    J

  8. Aaron Swindell

    Freakin’ awe­some! Both cubes… Found out about them (and you) in mag­a­zine “CSS Design Essen­tials” from UK. Jaw-dropping work! (Flash what???)

    Thank you so much for pub­lish­ing these goodies!

  9. Christopher Hester

    Amaz­ing! So smooth! But when I view the demo, there is half a YouTube video over­laid on the cube. Why is that? I am using Safari 5.0.3 on Win­dows XP. Lastly, saw this in the lat­est issue of .net mag­a­zine (April 2011, page 81).

  10. Sven Hoskens

    Hey Paul! Great work with this one, I’ve been mess­ing around with it a bit for a project of mine, but I’ve run into a lit­tle prob­lem. You see, I get the cube mov­ing and all that, no prob­lems, untill I decide to scale it a bit big­ger. It would appear that, once the size is altered, my cube still turns but the cen­tral axis upon which it turns doesn’t seem to be cor­rectly cen­tered any­more. So, every­time it turns, it shifts posi­tion slightly. The cube itself seems fine, but it just isn’t cen­tered as neatly any­more, mak­ing any addi­tional design and con­tent around it kinda tricky.

    Sorry to bother, and keep up the good work!

  11. Sven Hoskens

    Nev­er­mind, fixed it. Silly me. :D

  12. Mischa Magyar

    Wow that’s bril­liant!
    Using your code and some mod­i­fi­ca­tions I built a 3D cube menu for an uni­ver­sity project.

    May I share “our” code with the pub­lic (after clean­ing it up…)? :-)

    Thanks for sharing!

  13. Seth McDaniel

    I love the CSS ani­ma­tions, and all that is easy to under­stand, how­ever it would be great to have a deeply explained java script touch con­trols and it would be great if it was pure com­mented java script no out­side jquery sources or any­thing so as to really be able to pull apart and learn

  14. akarsh

    Please can u go in a bit detail of the changes from the pre­vi­ous ver­sion in all the 3 files?

  15. Chalassa

    Nice!! How to fix the prob­lem of blur when using “-webkit-perspective”? I have not found any solution.

  16. Anthony

    hi, I have been try­ing to recre­ate your cube for about a month, I nor to any of my web­de­signer friends have any idea of how to get it to work. What are we doing wrong?? can you help me? is there a more spe­cific instruc­tional or any­thing. I think this and all of your exper­i­ments are genius. Thanks.

  17. Gleb Popov

    Paul– very impres­sive indeed. I cre­ated a demo of my own where I essen­tially remote con­trol the 3D cube: http://​gle​bche​.appspot​.com/​3​dcube

  18. Eugene Tjoa

    I added a few script lines to make the cube rotate by rotat­ing your phone.

    http://​tjoad​e​sign​.nl/​b​l​o​g​/​?​p=350

  19. Smita

    This shows a sin­gle plane when we try to rotate it
    on android. What must be wrong

  20. doug

    really fine work. Of course, there are demos like this else­where (e.g., in WebGL), but what’s so impres­sive about your demo is that you used only the basic tools.