DEV Community

Cover image for Creating a 3D Cylinder shape in CSS
Chris Bongers
Chris Bongers

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

Creating a 3D Cylinder shape in CSS

Now that we created a dice and a pyramid in CSS, let's move on to a complex shape: The cylinder.

We have to mimic the cylinder because we don't have a CSS native box for round objects.

In my case, I'll be adding a lot of side panels that we skew next to each other.
This will mimic the 3D effect we are looking for.

The result for today will be this excellent-looking cylinder shape.

Creating a 3D Cylinder shape in CSS

HTML markup

I choose to make my demo in Pug. It's easy to mock up HTML as it can use variables.

However, what it comes down to is the following HTML output.

<div class="holder">
  <div class="cylinder">
    <div class="face" style="--index: 0;"></div>
    <div class="face" style="--index: 1;"></div>
    <!-- More faces! -->
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

I've added the holder wrapper so we can put that one at an angle without interfering with our actual cylinder.

I've added the following classes to the holder to achieve the slanted look.

.holder {
  transform-style: preserve-3d;
  transform: rotateX(-35deg);
}
Enter fullscreen mode Exit fullscreen mode

Styling a CSS 3D cylinder

Before we start, we need to define some variables as this one requires some calculation power.

I've decided to use SCSS as it's the easiest to use with variables.

Add the following variables in your CSS.

$pi: 3.14159265358979;
$cylinder-width: 100vw;
$face-count: 50;
$face-deg: (360deg / $face-count);
$face-width: ($cylinder-width / $face-count);
$face-shift: ($cylinder-width / $pi / 2);
Enter fullscreen mode Exit fullscreen mode

Let's go over each one.

  • pi: Matches PI, which we need to calculate a perfect circle shift size
  • cylinder-width: The width of our cylinder
  • face-count: How many faces we render. This should match the number of divs you added
  • face-deg: How much degree each face should cover
  • face-width: The width of each face
  • face-shift: We need to shift the faces outward to give it more of a round 3D effect

Now we can move on to the cylinder shape.

.cylinder {
  position: relative;
  height: 50vw;
  width: $cylinder-width;
  transform-style: preserve-3d;
}
Enter fullscreen mode Exit fullscreen mode

Nothing fancy here, but it basically will contain the wrapper for our cylinder sides.

Then we can move on to each face, sharing the same styling.

.face {
  position: absolute;
  background-color: #da0060;
  opacity: 0.7;
  height: 100%;
  width: $face-width;
  top: 50%;
  left: 50%;
  transform: rotateY(calc(#{$face-deg} * var(--index))) translateZ(
      calc(#{$face-shift} - -6px)
    );
}
Enter fullscreen mode Exit fullscreen mode

Each face is positioned with the width we calculated.
The main magic happens in the transform property.

We change the rotation on the Y axis, which places each face next to the other in a perfect circle.

So face one will get 7.2deg offset and the second one 14.4deg until we hit 360.

Note the 7.2 comes from 360 degrees / 50 (faces)

The translateZ is to push each item back a bit more, making it appear neater and more space.

I also decided to color one face differently to see the rotation better.

.face {
  &:nth-child(1) {
    background: purple;
  }
}
Enter fullscreen mode Exit fullscreen mode

Animating the cylinder

Let's add some animation to make the cylinder spin around.

@keyframes spin {
  to {
    transform: rotateY(-360deg);
  }
}

.cylinder {
  animation: spin 7s infinite linear;
}
Enter fullscreen mode Exit fullscreen mode

This will make the cylinder spin around the Y axis for 360 degrees.

You can see the result 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
 
posandu profile image
Posandu

A very interesting thing to create!

Collapse
 
dailydevtips1 profile image
Chris Bongers

Thanks, pretty fun to play around with.
I want to make some basic shapes and start putting them together 🤯