DEV Community

Joe Attardi
Joe Attardi

Posted on

Let's make a CSS cube

You can do a lot with CSS transforms! In this post we'll walk through making a 3D cube.

First, let's create the markup:

<div class="container">
  <div class="cube">
    <div class="face top">Top</div>
    <div class="face bottom">Bottom</div>
    <div class="face left">Left</div>
    <div class="face right">Right</div>
    <div class="face front">Front</div>
    <div class="face back">Back</div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Each face of the cube is its own div element. Let's create some initial styles:

.container {
  width: 200px;
  height: 200px;
  perspective: 500px;
  margin: 100px;
}

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

.face {
  width: 200px;
  height: 200px;
  background: skyblue;
  border: 2px solid black;
  position: absolute;
  opacity: 0.5;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: Arial, sans-serif;
  font-size: 2rem;
}
Enter fullscreen mode Exit fullscreen mode

We've given some styling to the cube faces and absolutely positioned them so they are all sitting on top of one another. First, we will rotate each face so that it's facing the proper direction. The next step will be to move each face out from the center to the edges of the cube.

Here is what we have so far:

The initial positioned elements

We are currently looking at the cube head-on. It will be easier to visualize if we rotate our "camera" a bit. Let's add a rotate3d transform to the cube:

.cube {
  position: relative;
  width: 200px;
  height: 200px;
  transform-style: preserve-3d;
  transform: rotate3d(1, 1, 0, 45deg);
}
Enter fullscreen mode Exit fullscreen mode

Now the elements are rotated at an angle, so we can see the 3D structure better:

Rotated in 3D space

Let's tackle the front first. Our cube is 200px by 200px by 200px. Currently all the elements are in the dead center of the cube. The front is already facing the right direction, we just need to move it out by 100px so that it is at the front edge. Let's add a new rule for the front and move it out:

.front {
  transform: translateZ(100px);
}
Enter fullscreen mode Exit fullscreen mode

Now the front face of the cube is in place:

The front face in position

Next is the back. It is already in the proper plane, but we need to rotate it 180 degrees around the y-axis so that the text is facing outwards. Like the front, we also need to move it out by 100px:

.back {
  transform: translateZ(-100px) rotateY(180deg);
}
Enter fullscreen mode Exit fullscreen mode

The back face is now in the proper position:

Back face in position

Let's do the left and right next. These need to be rotated 90 degrees around the y-axis so that they are both facing outwards on each side. The left side needs to be rotated by -90 degrees.

Then they need to be moved along the x-axis to the edges of the cube:

.left {
  transform: translateX(-100px) rotateY(-90deg);
}

.right {
  transform: translateX(100px) rotateY(90deg);
}
Enter fullscreen mode Exit fullscreen mode

Left and right in position

Lastly, we need to position the top and bottom. These need to be rotated 90 degrees around the x-axis so that they are facing up and down. Again, the top will need a rotation of 90 degrees and the bottom -90 degrees, so that the text direction is correct.

.top {
  transform: translateY(-100px) rotateX(90deg);
}

.bottom {
  transform: translateY(100px) rotateX(-90deg);
}
Enter fullscreen mode Exit fullscreen mode

The completed cube

Looks like a cube!

To show off our new cube, let's give it a turning animation:

@keyframes turn {
  from { transform: rotate3d(0, 0, 0, 0); }
  to { transform: rotate3d(1, 1, 0, 360deg); }
}

.cube {
  position: relative;
  width: 200px;
  height: 200px;
  transform-style: preserve-3d;
  animation: turn 5s linear infinite;
}
Enter fullscreen mode Exit fullscreen mode

Lastly, we want to be mindful of accessibility. If the user has disabled animations in their operating system, let's not animate the cube but rather display it at the 45 degree angle we had before:

@media (prefers-reduced-motion: reduce) {
  .cube {
    animation: none;
    transform: rotate3d(1, 1, 0, 45deg);
  }
}
Enter fullscreen mode Exit fullscreen mode

Here is the finished product in a CodePen:

Did you like this post? Learn more CSS in my upcoming book, Modern CSS!

Top comments (4)

Collapse
 
bitdweller profile image
Pedro Pimenta

Yeah! This is something I have never done. Always looked like something super-hard but it seems to be attainable for me :)

Thanks for the intro!

Collapse
 
mullojo profile image
Bob

Great job on explaining the steps here 😊 I had played with this ref, but didn't find it as easy to follow as your step by step approach.

Collapse
 
okyanusoz profile image
okyanusoz

Thank you for sharing this!

Collapse
 
nadya58s profile image
Nadia Sylvester

Perfect, thanks for sharing it.