Skillversitas

CSS 2D Transforms

2D transforms allow you to manipulate HTML elements in two dimensions — moving, rotating, enlarging/shrinking, and skewing elements without changing the document flow. A transformed element keeps its original space in the layout.

CSS transform works on the X axis (horizontal) and the Y axis (vertical). The result of a transform does not affect the position of other elements — this is different from properties like margin or position. A transform only affects the element's visual appearance.

Some of the available 2D transform functions:

  • translate() — moves an element from its original position
  • rotate() — rotates an element clockwise or counterclockwise
  • scale() — enlarges or shrinks an element
  • skew() — slants an element on a given axis
  • matrix() — combines all transforms in a single function

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 2D Transforms</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

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

    h1 {
      text-align: center;
      margin-bottom: 40px;
      color: #1a1a2e;
    }

    .demo-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 30px;
      max-width: 1000px;
      margin: 0 auto;
    }

    .demo-box {
      background: #fff;
      border-radius: 12px;
      padding: 30px 20px;
      text-align: center;
      box-shadow: 0 2px 10px rgba(0,0,0,0.08);
      transition: transform 0.3s ease, box-shadow 0.3s ease;
    }

    .demo-box:hover {
      box-shadow: 0 8px 25px rgba(0,0,0,0.15);
    }

    .demo-box h3 {
      margin-bottom: 15px;
      color: #16213e;
      font-size: 1rem;
    }

    .shape {
      width: 80px;
      height: 80px;
      background: linear-gradient(135deg, #667eea, #764ba2);
      margin: 0 auto 10px;
      border-radius: 8px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-weight: bold;
      font-size: 0.8rem;
    }

    /* Translate */
    .translate-demo:hover .shape {
      transform: translateX(30px);
    }

    /* Rotate */
    .rotate-demo:hover .shape {
      transform: rotate(45deg);
    }

    /* Scale */
    .scale-demo:hover .shape {
      transform: scale(1.3);
    }

    /* Skew */
    .skew-demo:hover .shape {
      transform: skewX(15deg);
    }

    /* Combined */
    .combined-demo:hover .shape {
      transform: translateX(20px) rotate(15deg) scale(1.1);
    }

    .code-label {
      display: block;
      margin-top: 10px;
      font-size: 0.7rem;
      color: #888;
      font-family: monospace;
      background: #f8f8f8;
      padding: 5px 8px;
      border-radius: 4px;
    }

    /* Transform Origin Demo */
    .origin-section {
      max-width: 1000px;
      margin: 50px auto 0;
    }

    .origin-section h2 {
      text-align: center;
      margin-bottom: 20px;
      color: #1a1a2e;
    }

    .origin-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
      gap: 20px;
    }

    .origin-box {
      background: #fff;
      border-radius: 12px;
      padding: 25px 15px;
      text-align: center;
      box-shadow: 0 2px 10px rgba(0,0,0,0.08);
    }

    .origin-box h4 {
      font-size: 0.85rem;
      margin-bottom: 12px;
      color: #16213e;
    }

    .origin-shape {
      width: 60px;
      height: 60px;
      background: #e74c3c;
      margin: 0 auto;
      border-radius: 4px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-size: 0.7rem;
    }

    .origin-center .origin-shape { transform-origin: center; }
    .origin-top-left .origin-shape { transform-origin: top left; }
    .origin-bottom-right .origin-shape { transform-origin: bottom right; }
    .origin-top .origin-shape { transform-origin: top center; }

    .origin-box:hover .origin-shape {
      transform: rotate(45deg);
    }

    /* Practical Example: Card Hover */
    .card-section {
      max-width: 600px;
      margin: 50px auto 0;
    }

    .card-section h2 {
      text-align: center;
      margin-bottom: 20px;
      color: #1a1a2e;
    }

    .hover-card {
      background: #fff;
      border-radius: 16px;
      overflow: hidden;
      box-shadow: 0 4px 15px rgba(0,0,0,0.1);
      transition: transform 0.4s ease, box-shadow 0.4s ease;
      cursor: pointer;
    }

    .hover-card:hover {
      transform: translateY(-8px) scale(1.02);
      box-shadow: 0 12px 35px rgba(0,0,0,0.2);
    }

    .hover-card-img {
      width: 100%;
      height: 200px;
      background: linear-gradient(135deg, #f093fb, #f5576c);
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-size: 2rem;
    }

    .hover-card-body {
      padding: 25px;
    }

    .hover-card-body h3 {
      color: #1a1a2e;
      margin-bottom: 10px;
    }

    .hover-card-body p {
      color: #666;
      line-height: 1.6;
      font-size: 0.9rem;
    }

    /* Practical Example: Icon Rotation */
    .icon-demo {
      max-width: 400px;
      margin: 50px auto 0;
      background: #fff;
      border-radius: 12px;
      padding: 25px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.08);
    }

    .icon-demo h2 {
      text-align: center;
      margin-bottom: 20px;
      color: #1a1a2e;
    }

    .dropdown-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 15px 20px;
      background: #f8f9fa;
      border-radius: 8px;
      margin-bottom: 10px;
      cursor: pointer;
      transition: background 0.3s ease;
    }

    .dropdown-item:hover {
      background: #e9ecef;
    }

    .dropdown-item span {
      font-weight: 500;
      color: #1a1a2e;
    }

    .arrow {
      width: 24px;
      height: 24px;
      background: #667eea;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-size: 0.8rem;
      transition: transform 0.3s ease;
      transform-origin: center;
    }

    .dropdown-item:hover .arrow {
      transform: rotate(90deg);
    }

    /* Practical Example: Zoom Effect */
    .zoom-section {
      max-width: 1000px;
      margin: 50px auto 0;
    }

    .zoom-section h2 {
      text-align: center;
      margin-bottom: 20px;
      color: #1a1a2e;
    }

    .zoom-grid {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 15px;
    }

    .zoom-item {
      aspect-ratio: 1;
      background: linear-gradient(135deg, #a18cd1, #fbc2eb);
      border-radius: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 2rem;
      cursor: pointer;
      transition: transform 0.3s ease;
      transform-origin: center;
    }

    .zoom-item:nth-child(2) { background: linear-gradient(135deg, #fad0c4, #ffd1ff); }
    .zoom-item:nth-child(3) { background: linear-gradient(135deg, #a1c4fd, #c2e9fb); }
    .zoom-item:nth-child(4) { background: linear-gradient(135deg, #d4fc79, #96e6a1); }

    .zoom-item:hover {
      transform: scale(1.15);
      z-index: 2;
    }
  </style>
</head>
<body>

  <h1>CSS 2D Transforms</h1>

  <div class="demo-grid">
    <div class="demo-box translate-demo">
      <h3>translateX(30px)</h3>
      <div class="shape"> Move </div>
      <code class="code-label">transform: translateX(30px)</code>
    </div>

    <div class="demo-box rotate-demo">
      <h3>rotate(45deg)</h3>
      <div class="shape"> Rotate </div>
      <code class="code-label">transform: rotate(45deg)</code>
    </div>

    <div class="demo-box scale-demo">
      <h3>scale(1.3)</h3>
      <div class="shape"> Bigger </div>
      <code class="code-label">transform: scale(1.3)</code>
    </div>

    <div class="demo-box skew-demo">
      <h3>skewX(15deg)</h3>
      <div class="shape"> Skewed </div>
      <code class="code-label">transform: skewX(15deg)</code>
    </div>

    <div class="demo-box combined-demo">
      <h3>Combination</h3>
      <div class="shape"> Combined </div>
      <code class="code-label">translate + rotate + scale</code>
    </div>
  </div>

  <div class="origin-section">
    <h2>Transform Origin</h2>
    <div class="origin-grid">
      <div class="origin-box origin-center">
        <h4>center (default)</h4>
        <div class="origin-shape">O</div>
      </div>
      <div class="origin-box origin-top-left">
        <h4>top left</h4>
        <div class="origin-shape">O</div>
      </div>
      <div class="origin-box origin-bottom-right">
        <h4>bottom right</h4>
        <div class="origin-shape">O</div>
      </div>
      <div class="origin-box origin-top">
        <h4>top center</h4>
        <div class="origin-shape">O</div>
      </div>
    </div>
  </div>

  <div class="card-section">
    <h2>Practice: Card Hover Effect</h2>
    <div class="hover-card">
      <div class="hover-card-img">🎨</div>
      <div class="hover-card-body">
        <h3>Interactive Card</h3>
        <p>Hover over this card to see the transform translate and scale effects working together.</p>
      </div>
    </div>
  </div>

  <div class="icon-demo">
    <h2>Practice: Spinning Icons</h2>
    <div class="dropdown-item">
      <span>Dropdown Menu</span>
      <div class="arrow">▶</div>
    </div>
    <div class="dropdown-item">
      <span>Settings</span>
      <div class="arrow">▶</div>
    </div>
    <div class="dropdown-item">
      <span>My Profile</span>
      <div class="arrow">▶</div>
    </div>
  </div>

  <div class="zoom-section">
    <h2>Practice: Zoom Effect</h2>
    <div class="zoom-grid">
      <div class="zoom-item">📷</div>
      <div class="zoom-item">🖼️</div>
      <div class="zoom-item">🏞️</div>
      <div class="zoom-item">🌄</div>
    </div>
  </div>

</body>
</html>

Code Explanation

translateX() and translateY()

translate() takes two parameters — a horizontal offset (X) and a vertical offset (Y). A positive X value moves the element to the right, a negative value to the left. For Y, positive moves it down and negative moves it up.

.shape {
  transform: translateX(30px);   /* shift 30px to the right */
  transform: translateY(-20px);  /* shift 20px up */
  transform: translate(30px, -20px); /* combination of both */
}

rotate()

The rotate() function takes values in degrees (deg). Positive values rotate clockwise, negative values counterclockwise.

.shape {
  transform: rotate(45deg);   /* rotate 45° clockwise */
  transform: rotate(-90deg);  /* rotate 90° counterclockwise */
}

scale()

The scale() function takes a decimal number. Values greater than 1 enlarge the element, values less than 1 shrink it, and exactly 1 is the normal size.

.shape {
  transform: scale(1.3);      /* enlarge by 30% */
  transform: scale(0.5);      /* shrink by 50% */
  transform: scale(1.5, 0.8); /* width 150%, height 80% */
}

skew()

The skew() function slants an element. The first parameter is the horizontal skew, the second parameter the vertical skew.

.shape {
  transform: skewX(15deg);    /* skew 15° horizontally */
  transform: skewY(10deg);    /* skew 10° vertically */
  transform: skew(15deg, 5deg); /* combination of both */
}

Transform Origin

transform-origin determines the center point of the transform. The default is center center (the middle of the element). You can set it to positions like top left, bottom right, or specific pixel/percentage values.

.shape {
  transform-origin: top left;   /* rotation point at top-left corner */
  transform-origin: 50% 100%;   /* bottom center */
  transform-origin: 0 0;        /* top-left corner (same as top left) */
}

matrix()

The matrix() function combines all 2D transforms in a single line. Six parameters: matrix(a, b, c, d, tx, ty) where a–d are the transform matrix values and tx/ty are the X/Y translate values. It is rarely written by hand — usually generated by visual tools.

.shape {
  /* Example of a matrix that produces translate(10px, 20px) */
  transform: matrix(1, 0, 0, 1, 10, 20);
}

Combining Transforms

You can combine multiple transform functions in a single declaration. Order matters — CSS applies transforms from right to left.

.shape {
  transform: translateX(20px) rotate(15deg) scale(1.1);
  /* applied: scale first, then rotate, then translate */
}

Everyday Use Cases

1. Hover Effect on Product Cards

In e-commerce, product cards often shift upward on hover to give a "lifted" feel:

.product-card {
  transition: transform 0.3s ease;
}

.product-card:hover {
  transform: translateY(-8px);
}

2. Rotating Dropdown Icons

A dropdown button whose arrow rotates 90° when clicked — this is a very common UI pattern:

.dropdown-arrow {
  transition: transform 0.3s ease;
}

.dropdown.active .dropdown-arrow {
  transform: rotate(90deg);
}

When the cursor enters a gallery image, the image scales up slightly to reveal detail:

.gallery-item img {
  transition: transform 0.4s ease;
}

.gallery-item:hover img {
  transform: scale(1.1);
}

4. Slide-in on a Mobile Menu

A side menu that slides in from the left when the hamburger button is clicked:

.sidebar {
  transform: translateX(-100%);
  transition: transform 0.3s ease;
}

.sidebar.open {
  transform: translateX(0);
}

5. Action Buttons with a Skew Effect

Some designs use skew to give CTA buttons a dynamic feel:

.cta-button {
  transform: skewX(-5deg);
}

.cta-button:hover {
  transform: skewX(-5deg) scale(1.05);
}

Conclusion

CSS 2D transforms give you the ability to manipulate elements visually without changing the document layout. translate() for movement, rotate() for rotation, scale() for resizing, and skew() for slanting. All of these functions can be combined, and their center point can be controlled using transform-origin. These transforms are most often used together with transition to create interactive animations such as hover effects, menu animations, and visual feedback on UI elements.