Create a 3D CSS Animated Box with Sass

by Brian Rinaldi on May 20, 2013

The modern web is always changing, and this article is more than two years old.

3d-box-header

By Jaime Quiroz

Working with 3D in CSS can be crazy fun to mess around with. Recently, I posted a simple animated 3D box on CodePen. As you can see below, the animation appears to split the 3D box n six direction. In this article I’ll show how I built the animation using Sass and some of the CSS 3D transforms and CSS animations it required.

Check out this Pen!

Building the Cube

The HTML to build this animation is exceedingly simple, being made up of only an unordered list with six list items representing each face of the cube.

<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

It is in the Sass where all the complexity lies. 94 lines of SASS may seem like a lot of effort to produce something a relatively short and simple animation like this. However, we keep in mind that we are both positioning the elements in 3D space as well as creating the keyframes for the animation.

If you’re working in 3D in CSS, there’s two things you need to get familiar with:

  1. transform-style: preserve-3d: this property is set on a container and enables child elements to be moved in 3D space;
  2. translateZ: this property is used on child elements of the container to move the element further and closer in 3D space.

So first we need to set transform-style: preserve-3d is set on the <ul> element as the container. With that in place the <li> elements are able to be manipulated in 3D space. Consider this line of code (note that I am using Sass with Compass in this example; add @import compass/css3 at the beginning of your SASS to enable all the awesome CSS3 mixins in Compass):

li:nth-child(1)
+transform(rotateX(90deg) translateZ(30px)

This makes the first list item in the unordered list rotate along the X axis 90 degrees. With that, the <li> would be facing up and would not be visible on the screen. However, now it can be moved up and down the screen using translateZ (instead of closer/further as the object is facing up).  In the above example, it is moved 30 pixels up. Alternatively, you’d use a negative  translateX value to move it down.

When you are working on an example like this, a good way to visualize what’s going on in 3D space is to rotate your container to an angle. In this example I did it like this:

ul
+transform(rotateX(45deg) rotateY(-45deg))

On the flip side, if you did rotateY(90deg) the <li> would be facing towards the right and could be moved from left to right using translateZ.

Adding the Animation

Once the li elements are moved into place we can start experimenting with animation. CSS animations will work on the latest Firefox and Opera with no prefix at all (although 3D transforms will not in Opera).

Compass doesn’t come with a keyframes mixin, so in this example I made my own to use -webkit- (for chrome, safari, iOS & android) and a prefix-less one for Firefox and Opera:

=keyframes($name)
    @-webkit-keyframes #{$name}
        @content
    @keyframes #{$name}
        @content

Which can be used like this:

+keyframes(pane1)
    to
        +transform(translateZ(150px))
        opacity: 0

li:nth-child(1)
-webkit-animation: pane1 2s infinite
animation: pane1 2s infinite

In this case, ‘Pane1’ is the name of the animation but you can call it anything you want.

Lets assume that in our CSS our first <li> was positioned with translateZ(75px).

The above ‘Pane1’ animation will move the <li> an additional 75px from its original position (i.e. 75px + 75px = 150px). Setting the opacity to zero makes it fade out at the end of the animation.

That’s pretty much it!

Protip* – CSS is very redundant but SASS is here to save the day! For example, in CSS you would have to add the animation property to every one of the <li> elements, but since only one thing is changing in the property (the animation name) we can use a SASS loop to help automate that:

@for $i from 1 to 7
&:nth-child(#{$i})
-webkit-animation: pane#{$i} 2s infinite
animation: pane#{$i} 2s infinite

In the above loop #{$i} will increment from 1 to 6 (when it gets to 7 nothing happens).

Where to Go From Here

If you are not using a CSS preprocessor yet, you are doing it wrong. There is absolutely no reason not to. I started using Sass about 2 years ago and I have never looked back. Compass gives you cool CSS3 mixins and is maintained by the Compass team so that you don’t ever have to worry about using an outdated syntax for the shiny CSS3 stuff.

CanIUse is another great resource that I use on almost a daily basis. It shows you what browser and devices are supporting what CSS properties and what vendor-prefixes are required as well.

For more details on 3D CSS, this tutorial is pretty excellent:

I look forward to seeing more awesome 3D CSS stuff on CodePen!

© 2017 Modern Web & our authors. All rights reserved.