Treehouse

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 HTML

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>
	</div>
</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.

The CSS

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!

ydkjs-3.png

Recent Features

  • Vibration&nbsp;API

    Many of the new APIs provided to us by browser vendors are more targeted toward the mobile user than the desktop user.  One of those simple APIs the Vibration API.  The Vibration API allows developers to direct the device, using JavaScript, to vibrate in...

  • CSS Animations Between Media&nbsp;Queries

    CSS animations are right up there with sliced bread. CSS animations are efficient because they can be hardware accelerated, they require no JavaScript overhead, and they are composed of very little CSS code. Quite often we add CSS transforms to elements via CSS during...

Incredible Demos

  • Send Email Notifications for Broken Images Using jQuery&nbsp;AJAX

    It's usually best to repair broken image paths as soon as possible because they can damage a website's credibility. And even worse is having a user tell you about it. Using jQuery and PHP, you can have your page automatically notify you of broken...

  • Optimize Your Links For Print Using CSS â Show The&nbsp;URL

    When moving around from page to page in your trusty browser, you get the benefit of hovering over links and viewing the link's target URL in the status bar. When it comes to page printouts, however, this obviously isn't an option. Most website printouts...

Discussion

  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 :)
    http://github.com/ivanbanov/polygonJS

  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 ?

  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.

    http://jordizle.com/demo/376/3d-interactive-cube-with-rotating-sides-using-css3-and-javascript/

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