DEV Community

Cover image for How to create a 3 dimensional object with CSS only

Posted on • Updated on

How to create a 3 dimensional object with CSS only

To become a better web developer you have to keep challenging yourself and keep learning new stuff. Thankfully I have amazing colleagues at Matise who are critical thinkers and always curious about new technologies, even while in self isolation. Last week I learned about the Observer api for example and I implemented it in two of our projects. This week I wanted to know how to make objects three dimensional with CSS, and in order to keep it fun I used a TARDIS as the object.

Transform styles and translating the Z axis

I started simpler of course; I did a little research and found that there are a couple of CSS properties you can use to create a 3d object.

One of the most important is transform-style, it has a default value of flat but needs to be set to preserve-3d; in order for the cube to become a cube. otherwise the sides will just be stacked on top of each other.

The perspective property lets you determine how far away the object is on the Z plane by adding any length value, which sounds really trippy. Increasing the perspective amount makes the object seem farther away. There's also a difference between the perspective property and perspective transform function, which is still a bit unclear to me to be honest.

The final property you'll need is the transform property which allows multiple transform functions like rotateY and rotateX, but also the very important translateZ property to assign positions on the z-axis per element.

Using rotate you can create a different perspective and see some of the top of the cube.

.cube {
  position: relative;
  transform-style: preserve-3d;
  transform: rotateX(-5deg) rotateY(1turn);
  // using a linear animation easing
  // to create an infinitely spinning cube
  animation: turn 12s linear infinite;
Enter fullscreen mode Exit fullscreen mode

A cube has six sides (unless you count the inside, hehehehe) so I had to add 6 divs which are all 10x10em. Somehow setting translateZ to half the width of the sides creates a pretty hotpink cube.

  .side {
    position: absolute;
    width: 10em;
    height: 10em;
    background: hotpink;
    &.front {
      transform: translateZ(5em);
    &.top {
      transform: rotateX(90deg) translateZ(5em);
    &.right {
      transform: rotateY(90deg) translateZ(5em);
    &.left {
      transform: rotateY(-90deg) translateZ(5em);
    &.bottom {
      transform: rotateX(-90deg) translateZ(5em);
    &.back {
      transform: rotateY(-180deg) translateZ(5em);
Enter fullscreen mode Exit fullscreen mode

Time and relative dimension in space

After successfully creating a cube I thought it was time for the real deal; a TARDIS. I created a TARDIS before but it had just one dimension which means it just wasn't good enough, because everyone knows a Tardis should spin.
Who am I to argue with history says Christoffer Eccleston
While a TARDIS is a little more complicated than a cube the principle is the same; set perspective: 800px; on the parent element and transform-style: preserve-3d; on the container element, and add 6 sides to transform.

The thing I struggled with most were things like the roof and the fact that once you've set a translateZ on a parent element the children aren't translatable on the z-axis anymore. Orrrr I was doing something wrong, please let me know if you know what.
The Doctor thinks you can do it!

You can do it too!

Let me know if you create any three dimensional stuff in CSS, bonus points if it's from Doctor Who. :)
The Doctor thinks you can do it too!

Top comments (8)

karataev profile image
Eugene Karataev

Great stuff!

Side note about images. I like funny gifs. But if a gif is near a text block I want to read, I'm always distracted by the animation. In this case I try to scroll out gifs from the viewport to avoid distraction.
If there are several gifs around and it's impossible to have animation-free viewport, I open the dev tools, execute document.querySelectorAll('img[src$=".gif"]').forEach(el => el.remove()) to remove gifs from the page and continue reading without distraction. Maybe it'll be helpful for anyone with similar feelings about animated images 😂

alvaromontoro profile image
Alvaro Montoro

Playing with 3D in CSS is fun. Here is a gazebo I built in CSS (probably the only way I can build one 😋)

amruthpillai profile image
Amruth Pillai

WOW! You have a lot of patience... and my respect. This is so fun to look at, definitely makes me excited to venture into the world of 3D CSS Modelling, but it would take me forever to get the math right :D

This is amazing :) Will look forward to more 3D models like this spreading the web soon.

iamdejean profile image
Jean Japheth Ezekiel

Awesome! I came across this article:

felipperegazio profile image
Felippe Regazio


_omggamer_ profile image

Great blog. Thanks.

pflash profile image
Precious adeyinka

Nice, thanks for sharing :)

utorrentgame profile image
gta 6 news

Nice work. I like it. Keep it up. Thanks for sharing with us.
GTA 5 Cheats PS5