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!

O'Reilly Velocity Conference
Save 20% with discount code AFF20

Recent Features

  • 6 Things You Didn&#8217;t Know About Firefox OS

    Firefox OS is all over the tech news and for good reason:  Mozilla's finally given web developers the platform that they need to create apps the way they've been creating them for years -- with CSS, HTML, and JavaScript.  Firefox OS has been rapidly improving,...

  • CSS Gradients

    With CSS border-radius, I showed you how CSS can bridge the gap between design and development by adding rounded corners to elements.  CSS gradients are another step in that direction.  Now that CSS gradients are supported in Internet Explorer 8+, Firefox, Safari, and Chrome,...

Incredible Demos

  • Using TogetherJS

    Last week I highlighted five awesome Mozilla technologies that most people have never heard of.  Before the Mozilla Summit in Santa Clara, even I (a Mozilla employee)  had not heard of a few of them.  One of the projects I was most impressed by...

  • MooTools History Plugin

    One of the reasons I love AJAX technology so much is because it allows us to avoid unnecessary page loads.  Why download the header, footer, and other static data multiple times if that specific data never changes?  It's a waste of time, processing, and bandwidth.  Unfortunately,...


  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 by Jeff Ballweg (@jeffballweg) on CodePen.”>http://codepen.io/jeffballweg/pen/ogxeaB/’ rel=”nofollow”>Pharma package in CSS by Jeff Ballweg (@jeffballweg) on CodePen.

      Pharma package in CSS by Jeff Ballweg (@jeffballweg) on CodePen." 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. Great tip. This is, what i wnat Thank you David ;)

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


  19. 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?

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

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

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

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

  • Open Files from Command Line on OS X

    I'm as much of a fan of application UIs as anyone else but I'm finding myself working more and more from the command line lately.  Much of that is becoming obsessed with media manipulation but I'm forcing myself to use less UIs so that I...

  • Get Stock Quotes From Command Line

    When I conned my way into my first professional programming gig, I didn't really think much about money -- just that I was getting my foot in the door.  But as my career has gone on, I've been more aware of money, investing, and retirement.  I've recently...

  • Geolocation API

    One interesting aspect of web development is geolocation; where is your user viewing your website from? You can base your language locale on that data or show certain products in your store based on the user's location. Let's examine how you can...

  • Create an Image Preview from a Video

    Visuals are everything when it comes to media.  When I'm trying to decide whether to watch a video on Netflix, it would be awesome to see a trailer of some kind, but alas that isn't available.  When I'm looking to download a video on my computer,...

  • New:  Webdesigner News!

    A new and exciting website has recently been launched for web designers and developers. You likely spend hours every morning browsing through hundreds of posts on your RSS feeds, hoping to stumble across relevant stories. Webdesigner News was built to provide web designers and developers with...