Create a 3D CSS Animated Box with Sass

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!

2 Comments

  1. DrClue said:

    The first order of business for me with all the neat CSS stuff was in ditching the vendor prefixing. Pure insanity to code ( -Khtml -Ms -O -Moz -Webkit -Web-Kit -atsc -wap -mso ) . In fewer lines of javascript then the insanity takes, one can be back to prefix free mental heath.

    It actually gets to be an amazing amount of fun after that. Among the elements are 3D form controls like roller wheels for dates and picking credit card types (touch and keyboard friendly) , and heck , even figured out how to make a pyramid complete with the brick texturing., by sorta setting the old CSS triangle trick on it’s ear with the border image, as many people might recall , the CSS triangle trick was meant to use the bevels of a thick bordered zero width box to produce a triangle and avoid downloading an image.

    One thing I’ve found is that direct manipulation of the CSSRules objects in the styleSheets can save a lot of grief. The same gizmo that makes authoring prefix free here also has sorta a querySelector that takes as arguments any number or order of strings,elements,RegExp and connects one to the appropriate CSSRule for the element the arguments describe.
    That one took up 20 lines of code , but I think it could loose nearly half that

    Anyways , good piece there. Seem to come across you in my casual Googling regularly.

*

*

Top