Create a CSS Cube

By on  
CSS Cube

CSS cubes really showcase what CSS has become over the years, evolving from simple color and dimension directives to a language capable of creating deep, creative visuals.  Add animation and you've got something really neat.  Unfortunately each CSS cube tutorial I've read is a bit long and a mixes visual style with the cube basics, so I've decided to write a post which provides just the basic detail needed to create a CSS cube.  I'm basing my example off of an outstanding CodePen demo by Mircea Georgescu.


The cube element, a wrapper in itself, will actually have a wrapper of its own:

<div class="wrap">
	<div class="cube">
		<div class="front">front</div>
		<div class="back">back</div>
		<div class="top">top</div>
		<div class="bottom">bottom</div>
		<div class="left">left</div>
		<div class="right">right</div>

Each face of the cube will have its own element.  As you can imagine, we'll be CSS-ing the hell out of them to put them in the proper position.


Let's take this one meaningful bit at a time.  The first meaningful element is the entire animation wrapper, which will provide a CSS perspective for the 3D element:

.wrap {
	perspective: 800px;
	perspective-origin: 50% 100px;

CSS perspective is a difficult concept to explain but MDN does a great job so I wont duplicate their explanation. To better understand perspective, I recommend modifying the perspective property to see how it effects the demo.  Next up is the cube container which will hold all of the different cube faces:

.cube {
	position: relative;
	width: 200px;
	transform-style: preserve-3d;

The cube will be 200 pixels wide, with relative positioning so that the absolutely positioned faces will stay within bounds.  We'll also use preserve-3d to keep the element 3D and not flat.  Before getting to any of the specific face rules, there will be a few general styles that will apply to each face:

.cube div {
	position: absolute;
	width: 200px;
	height: 200px;

With the position and dimensions of the faces set, we can get to creating the transformation code for individual faces:

.back {
	transform: translateZ(-100px) rotateY(180deg);
.right {
	transform: rotateY(-270deg) translateX(100px);
	transform-origin: top right;
.left {
	transform: rotateY(270deg) translateX(-100px);
	transform-origin: center left;
.top {
	transform: rotateX(-90deg) translateY(-100px);
	transform-origin: top center;
.bottom {
	transform: rotateX(90deg) translateY(100px);
	transform-origin: bottom center;
.front {
	transform: translateZ(100px);

The rotateY values rotate the faces of the to move the face show the text at the correct angled, while the translateZ setting moves the elements forward and backward within the stack.  The translateY setting may be confusing, but note that it represents raising or lowering a face to show 3D effect via the transparent panes.  Each face has its own translations settings to place them in the appropriate place, so feel free to modify those values to see why each corresponds to its face.

Horizontal Spinning of the Cube

Of course, what good is a 3D element set without animating it.  The answer:  none.  No good at all.  So here are a few steps we need to take to making our precious cube animate horizontally:

@keyframes spin {
	from { transform: rotateY(0); }
	to { transform: rotateY(360deg); }

.cube {
	animation: spin 5s infinite linear;

Probably easier than you think, yes?  The text looks correct due  to the facing rotation we implemented originally, and I've used keyframe animation in case we want to add more sexiness in the future.

Vertical Spinning of the Cube

Spinning the cube vertically should simple require changing the animation to Y axis, right?  Unfortunately not -- the panes as they are would show text backward in some cases, so we'll need to revise the rotation of a few elements:

@keyframes spin-vertical {
	from { transform: rotateX(0); }
	to { transform: rotateX(-360deg); }

.cube-wrap.vertical .cube {
	margin: 0 auto; /* keeps the cube centered */

	transform-origin: 0 100px;
	animation: spin-vertical 5s infinite linear;

.cube-wrap.vertical .top {
	transform: rotateX(-270deg) translateY(-100px);

.cube-wrap.vertical .back {
	transform: translateZ(-100px) rotateX(180deg);

.cube-wrap.vertical .bottom {
	transform: rotateX(-90deg) translateY(100px);

... as well as change the animation.

Flattening the Cube

To remove the 3D look of the cube, and simply display one block at a time (without other face hinting), remove the perspective and origin settings from the wrapper:

.wrap {
	/* no more perspective */
	perspective: none;
	perspective-origin: 0 0;

Now the only one face will display at any given time.

CSS cubes have been around for a while but I hope this article simplified their composition enough for you to attack your own.  And don't get discouraged if you run into issues creating your cube -- I did too!  I look forward to seeing what you create!

Track.js Error Reporting

Upcoming Events

Recent Features

  • Send Text Messages with PHP

    Kids these days, I tell ya.  All they care about is the technology.  The video games.  The bottled water.  Oh, and the texting, always the texting.  Back in my day, all we had was...OK, I had all of these things too.  But I still don't get...

  • Create a Sheen Logo Effect with CSS

    I was inspired when I first saw Addy Osmani's original ShineTime blog post.  The hover sheen effect is simple but awesome.  When I started my blog redesign, I really wanted to use a sheen effect with my logo.  Using two HTML elements and...

Incredible Demos

  • HTML5&#8217;s window.postMessage API

    One of the little known HTML5 APIs is the window.postMessage API.  window.postMessage allows for sending data messages between two windows/frames across domains.  Essentially window.postMessage acts as cross-domain AJAX without the server shims. Let's take a look at how window.postMessage works and how you...

  • Comment Preview Using MooTools

    Comment previewing is an awesome addition to any blog. I've seen really simple comment previewing and some really complex comment previewing. The following is a tutorial on creating very basic comment previewing using MooTools. The XHTML You can set up your XHTML any way you'd like....


  1. Fredrik

    Just a note, Firefox handles the cube in the same way as Chrome, if you add px after the numerical value, as stated here: https://developer.mozilla.org/en-US/docs/Web/CSS/perspective : perspective: 800px;

  2. I love how CSS evolved in the last few years. It’s been progressing faster and faster. :) I wonder where it will be in 5 years^^

  3. OssianGrr

    How much more complicated would it be to rotate the cube diagonally?

    • Changing the perspective-origin would allow you to do so!

  4. Thanks for the great tutorial! I used it for a CodePen I was working on. http://codepen.io/cliffpyles/pen/LHlqa

  5. Thanks for the tips and code, this is really useful!

  6. Awesome demo, like you say its great to see how far css has developed and progressed, exciting to see where things are going.

  7. Nice article and demo. Such a shame FF doesn’t anti-aliase as well as Chrome does, but at least it’s not as pants as Opera and IE10 which still aren’t on-board with any of this :-(

  8. Jeff Tackett

    Did you know that if you add a transparent outer box-shadow of 2px or more, then Firefox will render anti-aliased.
    box-shadow: 0px 0px 30px rgba(125, 125, 125, 0.8) inset, 0 0 4px rgba(0, 0, 0, 0);

  9. Hey, look my plugin for automatize this work :)

  10. Ron

    “The rotateY values rotate the faces of the to move the face show the text at the correct angled” that text doesn’t read very well.

  11. This is amazing!

    Any ideas on how to get it to work on IE 10 ?

    • IE10 doesn’t work because the method described here requires transform-style: preserve-3d; to be applied. Basically, in the method above, you create a box by transforming each of 6 faces, wrap those faces in a container, then animate the container (and its contents) in 3D space. IE10 does 3d-transforms, but it will not calculate a 3d-transform within another 3d-transform.

      To make it work, you can transform and animate each face relative to a central point. Note that each face must also be facing the correct direction for text to render properly.

      See the Pen Pharma package in CSS (@jeffballweg).
      “>http://codepen.io/jeffballweg/pen/ogxeaB/) by Jeff Ballweg (@jeffballweg).

      " data-user="jeffballweg">
  12. Roshdy

    Very nice tutorial.
    I’m just struggling with making the cube in % instead of px
    Can it be done?

  13. Thanks – very useful.
    Doesn’t seem to work correctly on Chrome 31 though.

  14. Interesting post! Unfortunately your Demo link goes to the Firefox animation (fire tail). At least this was true on Feb 10, 2014. Would love to see the Demo to determine if I should read the article in more detail. Thanks…

  15. Francis Underwood

    Would it be possible to make the cube smaller? I have been unable to make everything line up when I try. This is an awesome demo by the way! Thanks for sharing!

  16. Unknown

    Hi, how to build a “block” shape?
    I mean the height and the width is different

  17. Check out my 3d cube with rotating sides, it uses mouse and touch events to allow you to move it, while keeping the content of each side rotated the right way.


  18. Rafael

    I have a cube with various rotations, and want to have a more realistic shadow (actually, an ellipse). So I made this code to emulate it, based on your code:


    Is made for Chrome only (later I will modify it). The rotation is infinite, and I want to avoid the last anticlokwise jump of my shadow.

    Any idea about to solve this problem?

  19. works really well for me in linux firefox and chromium. I was struggling with it because I wanted to use percentages instead of absolute sizes, but percentage sizes don’t work with the rotating cube. However I found if I used VW units I could get the resizing I wanted and have it work with the rotating cube style. Not a solution for everyone I’m sure but still useful for a lot of situations.

  20. Very nice! It was fun to follow these instructions and create some thing really amazing!

  21. Taking CSS coding skills to another level! Really nice piece of code to fiddle with and use it as a basis to create other figures.

  22. Jason Clemens

    Great tutorial… thanks! Just a minor note: syntactically, the transform-origin property expects x-axis (left|center|right), then y-axis (top|center|bottom). I was getting lint errors until I realized your demo has them reversed (i.e. center left). Fortunately, most browsers can interpret these correctly.


Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • Get Node.js Command Line Arguments with yargs

    Using command line arguments within Node.js apps is par for the course, especially when you're like me and you use JavaScript to code tasks (instead of bash scripts).  Node.js provides process.argv but that doesn't provide a key: value object like you'd expect: Bleh.  If you want to work with a...

  • OâReilly Velocity Conference â New York

    My favorite front-end conference has always been O'Reilly's Velocity Conference because the conference series has focused on one of the most undervalued parts of client side coding:  speed.  So often we're so excited that our JavaScript works that we forget that speed, efficiency, and performance are just as important. The next Velocity...

  • Free Download: Font Bundle Featuring 17 Incredible Typefaces

    The only thing we love more than a good font, is a good free font. So we’ve combed the Web for some of our favorite free fonts, and gathered them here in a single download. You’ll find a variety of useful typefaces, from highly geometric designs...

  • OâReilly Velocity Conference â Amsterdam

    My favorite front-end conference has always been O'Reilly's Velocity Conference because the conference series has focused on one of the most undervalued parts of client side coding:  speed.  So often we're so excited that our JavaScript works that we forget that speed, efficiency, and performance are just as important. The next Velocity...

  • CanIUse Command Line

    Every front-end developer should be well acquainted with CanIUse, the website that lets you view browser support for browser features.  When people criticize my blog posts for not detailing browser support for features within the post, I tell them to check CanIUse:  always up to date, unlike...