Skillversitas

CSS 3D Transforms

3D transforms allow you to manipulate elements in three dimensions — adding depth (the Z axis) in addition to width (X) and height (Y). With 3D transforms, you can create effects such as flipping cards, rotating cubes, and three-dimensional carousels.

For 3D transforms to work, you need to define perspective on the parent element. Perspective determines how far the viewport is from the element — the smaller the value, the more dramatic the 3D effect.

Key concepts of 3D transforms:

  • perspective — viewing distance from the viewer to the element
  • rotateX() — rotates an element around the horizontal axis
  • rotateY() — rotates an element around the vertical axis
  • rotateZ() — rotates an element around the depth axis (same as 2D rotate)
  • translateZ() — moves an element toward/away from the viewer
  • transform-style: preserve-3d — preserves 3D space for child elements
  • backface-visibility — controls the visibility of an element's back side

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS 3D Transforms</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background: #0f0f1a;
      color: #fff;
      padding: 40px 20px;
    }

    h1 {
      text-align: center;
      margin-bottom: 10px;
    }

    .subtitle {
      text-align: center;
      color: #888;
      margin-bottom: 50px;
    }

    .demo-row {
      display: flex;
      justify-content: center;
      gap: 60px;
      flex-wrap: wrap;
      margin-bottom: 60px;
    }

    .demo-item {
      text-align: center;
    }

    .demo-item h3 {
      margin-bottom: 20px;
      font-size: 0.9rem;
      color: #aaa;
    }

    /* ===== Rotate X Demo ===== */
    .rotate-x-scene {
      perspective: 600px;
      width: 150px;
      height: 150px;
    }

    .rotate-x-box {
      width: 100%;
      height: 100%;
      background: linear-gradient(135deg, #667eea, #764ba2);
      border-radius: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
      transition: transform 0.6s ease;
      transform-style: preserve-3d;
    }

    .rotate-x-scene:hover .rotate-x-box {
      transform: rotateX(30deg);
    }

    /* ===== Rotate Y Demo ===== */
    .rotate-y-scene {
      perspective: 600px;
      width: 150px;
      height: 150px;
    }

    .rotate-y-box {
      width: 100%;
      height: 100%;
      background: linear-gradient(135deg, #f093fb, #f5576c);
      border-radius: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
      transition: transform 0.6s ease;
      transform-style: preserve-3d;
    }

    .rotate-y-scene:hover .rotate-y-box {
      transform: rotateY(30deg);
    }

    /* ===== Translate Z Demo ===== */
    .translate-z-scene {
      perspective: 600px;
      width: 150px;
      height: 150px;
    }

    .translate-z-box {
      width: 100%;
      height: 100%;
      background: linear-gradient(135deg, #4facfe, #00f2fe);
      border-radius: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
      transition: transform 0.6s ease;
    }

    .translate-z-scene:hover .translate-z-box {
      transform: translateZ(50px);
    }

    /* ===== 3D Card Flip ===== */
    .flip-section {
      max-width: 350px;
      margin: 0 auto 60px;
    }

    .flip-section h2 {
      text-align: center;
      margin-bottom: 20px;
    }

    .card-flip-container {
      perspective: 1000px;
      width: 300px;
      height: 400px;
      margin: 0 auto;
      cursor: pointer;
    }

    .card-flip {
      width: 100%;
      height: 100%;
      position: relative;
      transform-style: preserve-3d;
      transition: transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
    }

    .card-flip-container:hover .card-flip {
      transform: rotateY(180deg);
    }

    .card-front,
    .card-back {
      position: absolute;
      width: 100%;
      height: 100%;
      backface-visibility: hidden;
      border-radius: 16px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 30px;
    }

    .card-front {
      background: linear-gradient(135deg, #667eea, #764ba2);
      color: white;
    }

    .card-front .card-icon {
      font-size: 4rem;
      margin-bottom: 20px;
    }

    .card-front h3 {
      font-size: 1.5rem;
      margin-bottom: 10px;
    }

    .card-front p {
      opacity: 0.8;
      text-align: center;
      line-height: 1.5;
    }

    .card-back {
      background: linear-gradient(135deg, #f5576c, #ff6b6b);
      color: white;
      transform: rotateY(180deg);
    }

    .card-back h3 {
      font-size: 1.3rem;
      margin-bottom: 15px;
    }

    .card-back p {
      text-align: center;
      line-height: 1.6;
      opacity: 0.9;
    }

    .card-back .card-back-icon {
      font-size: 3rem;
      margin-top: 15px;
    }

    /* ===== 3D Cube ===== */
    .cube-section {
      max-width: 500px;
      margin: 0 auto 60px;
      text-align: center;
    }

    .cube-section h2 {
      margin-bottom: 10px;
    }

    .cube-section .hint {
      color: #888;
      margin-bottom: 30px;
      font-size: 0.85rem;
    }

    .cube-scene {
      width: 200px;
      height: 200px;
      perspective: 600px;
      margin: 0 auto;
    }

    .cube {
      width: 100%;
      height: 100%;
      position: relative;
      transform-style: preserve-3d;
      animation: rotateCube 8s infinite linear;
    }

    @keyframes rotateCube {
      0% { transform: rotateX(0deg) rotateY(0deg); }
      100% { transform: rotateX(360deg) rotateY(360deg); }
    }

    .cube-face {
      position: absolute;
      width: 200px;
      height: 200px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 1.5rem;
      font-weight: bold;
      border: 2px solid rgba(255,255,255,0.2);
      border-radius: 4px;
    }

    .cube-front  { background: rgba(102, 126, 234, 0.8); transform: rotateY(0deg) translateZ(100px); }
    .cube-back   { background: rgba(118, 75, 162, 0.8);  transform: rotateY(180deg) translateZ(100px); }
    .cube-right  { background: rgba(240, 147, 251, 0.8); transform: rotateY(90deg) translateZ(100px); }
    .cube-left   { background: rgba(245, 87, 108, 0.8);  transform: rotateY(-90deg) translateZ(100px); }
    .cube-top    { background: rgba(79, 172, 254, 0.8);  transform: rotateX(90deg) translateZ(100px); }
    .cube-bottom { background: rgba(0, 242, 254, 0.8);   transform: rotateX(-90deg) translateZ(100px); }

    /* ===== 3D Carousel ===== */
    .carousel-section {
      max-width: 500px;
      margin: 0 auto;
      text-align: center;
    }

    .carousel-section h2 {
      margin-bottom: 30px;
    }

    .carousel-scene {
      width: 250px;
      height: 350px;
      perspective: 800px;
      margin: 0 auto;
    }

    .carousel {
      width: 100%;
      height: 100%;
      position: relative;
      transform-style: preserve-3d;
      animation: rotateCarousel 12s infinite linear;
    }

    @keyframes rotateCarousel {
      0% { transform: rotateY(0deg); }
      100% { transform: rotateY(360deg); }
    }

    .carousel-item {
      position: absolute;
      width: 250px;
      height: 350px;
      border-radius: 16px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      font-size: 1.2rem;
      font-weight: bold;
      backface-visibility: hidden;
      border: 2px solid rgba(255,255,255,0.1);
    }

    .carousel-item:nth-child(1) {
      background: linear-gradient(135deg, #667eea, #764ba2);
      transform: rotateY(0deg) translateZ(350px);
    }

    .carousel-item:nth-child(2) {
      background: linear-gradient(135deg, #f093fb, #f5576c);
      transform: rotateY(60deg) translateZ(350px);
    }

    .carousel-item:nth-child(3) {
      background: linear-gradient(135deg, #4facfe, #00f2fe);
      transform: rotateY(120deg) translateZ(350px);
    }

    .carousel-item:nth-child(4) {
      background: linear-gradient(135deg, #43e97b, #38f9d7);
      transform: rotateY(180deg) translateZ(350px);
    }

    .carousel-item:nth-child(5) {
      background: linear-gradient(135deg, #fa709a, #fee140);
      transform: rotateY(240deg) translateZ(350px);
    }

    .carousel-item:nth-child(6) {
      background: linear-gradient(135deg, #a18cd1, #fbc2eb);
      transform: rotateY(300deg) translateZ(350px);
    }

    .carousel-item-icon {
      font-size: 3rem;
      margin-bottom: 15px;
    }

    .code-block {
      max-width: 700px;
      margin: 40px auto;
      background: #1a1a2e;
      border-radius: 12px;
      padding: 25px;
      overflow-x: auto;
    }

    .code-block h3 {
      margin-bottom: 15px;
      color: #667eea;
      font-size: 0.9rem;
    }

    .code-block pre {
      color: #e0e0e0;
      font-family: 'Fira Code', monospace;
      font-size: 0.85rem;
      line-height: 1.6;
    }
  </style>
</head>
<body>

  <h1>CSS 3D Transforms</h1>
  <p class="subtitle">Interaction: hover over the box to see the 3D effect</p>

  <div class="demo-row">
    <div class="demo-item">
      <h3>rotateX(30deg)</h3>
      <div class="rotate-x-scene">
        <div class="rotate-x-box">X</div>
      </div>
    </div>

    <div class="demo-item">
      <h3>rotateY(30deg)</h3>
      <div class="rotate-y-scene">
        <div class="rotate-y-box">Y</div>
      </div>
    </div>

    <div class="demo-item">
      <h3>translateZ(50px)</h3>
      <div class="translate-z-scene">
        <div class="translate-z-box">Z</div>
      </div>
    </div>
  </div>

  <div class="flip-section">
    <h2>3D Card Flip</h2>
    <div class="card-flip-container">
      <div class="card-flip">
        <div class="card-front">
          <div class="card-icon">💳</div>
          <h3>Credit Card</h3>
          <p>Hover to see the details on the back of the card</p>
        </div>
        <div class="card-back">
          <h3>Card Details</h3>
          <p>Number: **** **** **** 1234</p>
          <p>Valid: 12/28</p>
          <p>CVV: ***</p>
          <div class="card-back-icon">🔒</div>
        </div>
      </div>
    </div>
  </div>

  <div class="cube-section">
    <h2>3D Rotating Cube</h2>
    <p class="hint">The cube rotates automatically using CSS animation</p>
    <div class="cube-scene">
      <div class="cube">
        <div class="cube-face cube-front">Depan</div>
        <div class="cube-face cube-back">Belakang</div>
        <div class="cube-face cube-right">Right</div>
        <div class="cube-face cube-left">Left</div>
        <div class="cube-face cube-top">Top</div>
        <div class="cube-face cube-bottom">Bottom</div>
      </div>
    </div>
  </div>

  <div class="carousel-section">
    <h2>3D Carousel</h2>
    <div class="carousel-scene">
      <div class="carousel">
        <div class="carousel-item">
          <div class="carousel-item-icon">🎵</div>
          Musik
        </div>
        <div class="carousel-item">
          <div class="carousel-item-icon">📷</div>
          Photo
        </div>
        <div class="carousel-item">
          <div class="carousel-item-icon">🎬</div>
          Video
        </div>
        <div class="carousel-item">
          <div class="carousel-item-icon">📚</div>
          Book
        </div>
        <div class="carousel-item">
          <div class="carousel-item-icon">🎮</div>
          Game
        </div>
        <div class="carousel-item">
          <div class="carousel-item-icon">🎨</div>
          Seni
        </div>
      </div>
    </div>
  </div>

  <div class="code-block">
    <h3>How to Build a 3D Cube</h3>
    <pre>
/* 1. Create a scene with perspective */
.cube-scene {
  perspective: 600px;
}

/* 2. Enable preserve-3d on the parent */
.cube {
  transform-style: preserve-3d;
}

/* 3. Position each face */
.cube-front {
  transform: rotateY(0deg) translateZ(100px);
}

.cube-back {
  transform: rotateY(180deg) translateZ(100px);
}

.cube-right {
  transform: rotateY(90deg) translateZ(100px);
}
    </pre>
  </div>

</body>
</html>

Code Explanation

perspective

perspective is declared on the parent element that acts as the 3D "scene". Its value is in pixels — it determines how far the viewer is from the element. The smaller the value, the more dramatic the 3D effect.

.scene {
  perspective: 600px;  /* viewer 600px away from the element */
}

You can also apply perspective directly to the transformed element, but the result is different — each child will have its own independent perspective.

rotateX() and rotateY()

  • rotateX() rotates the element around the horizontal axis (the pivot is at the horizontal center). Imagine the element "tilting forward" or "tilting backward".
  • rotateY() rotates the element around the vertical axis. Imagine the element "spinning like a door".
.box {
  transform: rotateX(30deg);  /* tilt 30° forward */
  transform: rotateY(90deg);  /* rotate 90° to the left */
}

translateZ()

translateZ() moves an element along the depth axis. Positive values move it toward the viewer (it appears larger), negative values move it away (it appears smaller).

.box {
  transform: translateZ(50px);   /* move 50px closer */
  transform: translateZ(-50px);  /* move 50px away */
}

transform-style: preserve-3d

This property must be enabled on the parent element so that its children preserve 3D space. Without it, all children are flattened onto a single 2D plane.

.parent {
  transform-style: preserve-3d;
}

backface-visibility

This property controls whether the back side of an element is visible when it is rotated past 180°. The hidden value hides the back side — important for card flip effects.

.card-front {
  backface-visibility: hidden;  /* hide the back side */
}

.card-back {
  backface-visibility: hidden;
  transform: rotateY(180deg);  /* already rotated, so it appears from the front */
}

Building a 3D Cube

A cube consists of 6 faces. Each face is positioned using a combination of rotateY() or rotateX() and translateZ(). The translateZ distance must equal half of the cube's width.

/* For a 200x200px cube, translateZ = 100px */
.front  { transform: rotateY(0deg)   translateZ(100px); }
.back   { transform: rotateY(180deg) translateZ(100px); }
.right  { transform: rotateY(90deg)  translateZ(100px); }
.left   { transform: rotateY(-90deg) translateZ(100px); }
.top    { transform: rotateX(90deg)  translateZ(100px); }
.bottom { transform: rotateX(-90deg) translateZ(100px); }

Building a Card Flip

A card flip uses two stacked elements — front and back. Both have backface-visibility: hidden. The front faces normally, the back is rotated 180°. When the parent is rotated 180°, the front disappears and the back appears.

.card-container {
  perspective: 1000px;
}

.card {
  transform-style: preserve-3d;
  transition: transform 0.8s ease;
}

.card:hover {
  transform: rotateY(180deg);
}

.card-front { backface-visibility: hidden; }
.card-back  { backface-visibility: hidden; transform: rotateY(180deg); }

A 3D carousel is a ring of items, each rotated at even intervals. For example, 6 items = each item rotated 60° (360/6). Each item is also translated along Z by the ring's radius.

/* 6 items, each rotateY = 60° × index */
.item:nth-child(1) { transform: rotateY(0deg)   translateZ(350px); }
.item:nth-child(2) { transform: rotateY(60deg)  translateZ(350px); }
.item:nth-child(3) { transform: rotateY(120deg) translateZ(350px); }
/* ...etc */

Everyday Use Cases

1. Bank Cards in a Fintech App

Many banking apps display a virtual card that can be "flipped" to reveal account details. This uses a card flip with rotateY(180deg) and backface-visibility: hidden.

2. Depth Effects on a Landing Page

Some websites add depth effects with translateZ and perspective to make certain elements "float" above other content when scrolled or hovered.

3. Product Showcase 3D

Product showcase websites often display product images that can be rotated 360° using rotateY with a drag interaction (using JavaScript to change the rotate value based on cursor position).

A 3D image gallery that displays images in carousel format — each image positioned in a ring formation using rotateY and translateZ, rotating automatically or when the user interacts.

5. Game Menus on Websites

Some game websites use 3D menus such as rotating cubes or card carousels for navigation — providing a more immersive visual experience than ordinary menus.

Conclusion

CSS 3D transforms add a depth dimension to element manipulation. perspective on the parent determines the intensity of the 3D effect. rotateX(), rotateY(), rotateZ(), and translateZ() control rotation and movement on the third axis. transform-style: preserve-3d preserves 3D space for child elements, and backface-visibility controls the visibility of the back side. These techniques make it possible to build card flips, 3D cubes, carousels, and other depth effects without JavaScript or additional libraries.