DEV Community

Cover image for Creating a 3D dice in CSS
Chris Bongers
Chris Bongers

Posted on • Originally published at daily-dev-tips.com

Creating a 3D dice in CSS

I'm finally going to touch on a subject I've been putting off for way too long in this article.

3D in CSS!

Yes, 3D, and what better example of trying and making a 3D dice in CSS.

The result of this article will be this rotating dice.
(Code and demo at the bottom)

Creating a 3D dice in CSS

Setting up the HTML

Let's start with the HTML. We need a dice container and six sides to it.



<div class="dice">
  <div class="side one"></div>
  <div class="side two"></div>
  <div class="side three"></div>
  <div class="side four"></div>
  <div class="side five"></div>
  <div class="side six"></div>
</div>


Enter fullscreen mode Exit fullscreen mode

That will be all for our HTML part. Let's quickly move on to the fun part, which will be the CSS.

Basic styling

Let's start with some basic styling.

First, I ensured the dice element was in the middle of the page since it's easier to work with.



body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}


Enter fullscreen mode Exit fullscreen mode

Then I moved on to arranging the dice to be a big square box.



.dice {
  position: relative;
  width: 200px;
  height: 200px;
}


Enter fullscreen mode Exit fullscreen mode

Then each side is another wrapper that centers all its children (the dots).



.side {
  width: 100%;
  height: 100%;
  background: #da0060;
  border: 2px solid black;
  position: absolute;
  opacity: 0.7;
  display: flex;
  align-items: center;
  justify-content: center;
}


Enter fullscreen mode Exit fullscreen mode

By now, you should see something that looks like this:

Dice wireframe setup

It might not look like much, but trust me, there are six sides!

Creating dice dots in CSS

I will start by explaining how I achieved the dots since this is quite an excellent technique.

I didn't want to use a lot of extra divs, so each option only consists of one pseudo selector.

And it starts with the #1 side.



.side {
  &:before {
    content: '';
    width: 20%;
    height: 20%;
    background: black;
    border-radius: 50%;
  }
}


Enter fullscreen mode Exit fullscreen mode

One dot on the dice in CSS

I can hear you think, but what about the others?

And there is a very cool trick for that! We can leverage the box-shadow rule for it.

And if we think about it, there are only seven positions a dot can have.
We already have one, so let's look at the other six.



&:before {
  content: '';
  width: 20%;
  height: 20%;
  background: black;
  border-radius: 50%;
  box-shadow: red -50px -50px 0px 0px, blue -50px 0px 0px 0px,
    yellow -50px 50px 0px 0px, green 50px -50px 0px 0px, orange 50px 0px 0px 0px,
    white 50px 50px 0px 0px;
}


Enter fullscreen mode Exit fullscreen mode

I used random colors in the example above so you can see which position is which dot.

All possible dots in CSS

Note: The black dot is our initial dot.

Now let's go ahead and create all possible dot variants.

For the #2 side, we don't need the initial dot so that we can turn off the background.



.two {
  &:before {
    background: transparent;
    box-shadow: #000 -50px -50px 0px 0px, #000 50px 50px 0px 0px;
  }
}


Enter fullscreen mode Exit fullscreen mode

For number three we can use a similar approach, but not hide the background:



.three {
  &:before {
    box-shadow: #000 -50px 50px 0px 0px, #000 50px -50px 0px 0px;
  }
}


Enter fullscreen mode Exit fullscreen mode

Then for the fourth one:



.four {
  &:before {
    background: transparent;
    box-shadow: #000 -50px 50px 0px 0px, #000 -50px -50px 0px 0px,
      #000 50px 50px 0px 0px, #000 50px -50px 0px 0px;
  }
}


Enter fullscreen mode Exit fullscreen mode

And on to number five:



.five {
  &:before {
    box-shadow: #000 -50px -50px 0px 0px, #000 -50px 50px 0px 0px,
      #000 50px -50px 0px 0px, #000 50px 50px 0px 0px;
  }
}


Enter fullscreen mode Exit fullscreen mode

And last but not least, number six, which we used as our template.



.six {
  &:before {
    background: transparent;
    box-shadow: #000 -50px -50px 0px 0px, #000 -50px 0px 0px 0px,
      #000 -50px 50px 0px 0px, #000 50px -50px 0px 0px, #000 50px 0px 0px 0px, #000
        50px 50px 0px 0px;
  }
}


Enter fullscreen mode Exit fullscreen mode

Our result will look weird since our transparent layers sit on each other.

Dice dots in CSS

Arranging a dice in 3D CSS

Now that we have all our elements in place let's start the fun and apply our 3D effect!

We can achieve a 3D perspective in CSS by using transforms. We have three axes to play with: the X, Y, and Z axes.

First, let's put our cube in perspective.



.dice {
  transform-style: preserve-3d;
  transform: rotateY(185deg) rotateX(150deg) rotateZ(315deg);
}


Enter fullscreen mode Exit fullscreen mode

Now, it might look a bit weird if we look at what we got.

3D effect in CSS

This is already 3D, but it doesn't look like a cube yet. We need to modify each side to do its transformation.

Let's start with side one.



.one {
  transform: translateZ(100px);
}


Enter fullscreen mode Exit fullscreen mode

This will lift the side, so it sticks out at the top.

3D CSS cube lifting one side

You might already be able to see where this is going.
Now let's do the opposite end, which is side number six.

We will offset that to a negative 100px. This means the distance between one and six is now 200px (our cube size).



.six {
  transform: translateZ(-100px);
}


Enter fullscreen mode Exit fullscreen mode

CSS Dice two sides offset

Now let's do the number two side. This one needs to be connected by transforming a different axis.



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


Enter fullscreen mode Exit fullscreen mode

Side number two CSS dice

Now the easiest one to connect is the opposite, side number five.



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


Enter fullscreen mode Exit fullscreen mode

As you can see, it's the same transformation, but we offset it by 200 pixels.

Side number 5 CSS dice

Two more sides left. Let's do number three.



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


Enter fullscreen mode Exit fullscreen mode

As you can see, it's the opposite transformation from two to five.

Side number three

The last one we need is number four, which will be the opposite of number three.



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


Enter fullscreen mode Exit fullscreen mode

With this one in place, our dice are complete!

3D Dice made in CSS

Animating the dice

Now that we have our dice let's make it a bit more interactive by animating it!

Each of the sides we described can also be animated, I'll only be turning the dice on one side, but you can have a play around with any of them to achieve a different animation.



@keyframes rotate {
  from {
    transform: rotateY(0) rotateX(45deg) rotateZ(45deg);
  }
  to {
    transform: rotateY(360deg) rotateX(45deg) rotateZ(45deg);
  }
}

.dice {
  animation: rotate 5s linear infinite;
}


Enter fullscreen mode Exit fullscreen mode

You can find the completed example in this CodePen.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Top comments (2)

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

This looks wrong. It looks more like an orthographic projection with no perspective.

Compare with this.

You need to use the perspective and perspective-origin CSS properties.

Collapse
 
dailydevtips1 profile image
Chris Bongers

It's not "wrong" it's simply missing the perspective yes.
My idea is to make first steps into creating 3D with CSS.

In my follow articles I learn about perspective and will apply that.
Not really a big fan of the words: Wrong, need to use though.