CSS · Selectors & Effects

Transforms

Transforms move, resize, rotate and tilt elements visually — without disturbing the layout around them. They power most smooth effects on the web.

Intermediate 5 min Lesson 19 of 26 Runnable examples
Before you start:Positioning
0/26 in CSS
On this page · 5 min · Intermediate

Learning objectives#

  • Use translate, scale, rotate and skew
  • Change the pivot point with transform-origin
  • Combine multiple transforms in the right order
  • Create a simple 3D flip

Explanation#

translate(x, y) moves an element; scale(1.2) makes it 20% bigger; rotate(45deg) turns it; skew(10deg) slants it.

Transforms are visual only. The element keeps its original space in the layout, so neighbours do not move.

transform-origin sets the pivot. The default is the centre; transform-origin: top left rotates around the top-left corner.

Multiple transforms go in one property, applied right to left: transform: translateX(50px) rotate(45deg). Order changes the result.

Classic centring trick: position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%).

3D: perspective on the parent plus rotateY() on the child creates depth; backface-visibility: hidden hides the back side.

Code example: Transforms gallery and a flip card#

HTMLTransforms gallery and a flip card Runnable
<style>
  body { font-family: sans-serif; padding: 20px; }
  .row { display: flex; gap: 30px; margin-bottom: 30px; }
  .b { width: 70px; height: 70px; background: #a5b4fc; display: grid; place-items: center; font-size: 12px; }
  .t1 { transform: translate(10px, 10px); }
  .t2 { transform: scale(1.2); }
  .t3 { transform: rotate(20deg); }
  .t4 { transform: skewX(-15deg); }
  .t5 { transform-origin: top left; transform: rotate(20deg); }


  .flip { width: 160px; height: 100px; perspective: 600px; }
  .inner { position: relative; width: 100%; height: 100%; transition: transform 600ms; transform-style: preserve-3d; }
  .flip:hover .inner { transform: rotateY(180deg); }
  .face { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 10px; backface-visibility: hidden; color: white; }
  .front { background: #2965f1; }
  .back  { background: #16a34a; transform: rotateY(180deg); }
</style>


<div class="row">
  <div class="b t1">translate</div><div class="b t2">scale</div><div class="b t3">rotate</div>
  <div class="b t4">skew</div><div class="b t5">origin</div>
</div>
<div class="flip"><div class="inner">
  <div class="face front">Hover to flip</div>
  <div class="face back">Hello! 👋</div>
</div></div>
Expected output
Five boxes moved, enlarged, rotated, slanted and rotated around a corner, plus a blue card that flips in 3D to a green back side on hover.
Opens this example in the full playground

Step-by-step explanation#

  1. translate moves the first box without pushing others.
  2. scale(1.2) enlarges the second box by 20%.
  3. rotate and skew change angles.
  4. transform-origin: top left pivots the last box from its corner.
  5. perspective on .flip gives 3D depth; rotateY(180deg) turns the card over.
  6. backface-visibility: hidden hides whichever face is pointing away.

Real-world use case#

Hover zoom on product photos, slide-in menus (translateX), rotating chevrons on accordions and flip cards for flashcards all use transforms.

Common mistakes#

Two transform declarations

transform: rotate(10deg); transform: scale(2); — the second replaces the first. Combine them: transform: rotate(10deg) scale(2).

Expecting neighbours to move

A scaled element overlaps neighbours instead of pushing them. Leave space or use layout properties if you need reflow.

Blurry text after scale

Scaling text up from a small size can blur it. Prefer changing font-size for permanent sizes.

Best practices#

  • Use transforms for movement instead of top/left
  • Combine transforms in one declaration
  • Pair transforms with transitions for smooth effects
  • Use the individual translate, rotate and scale properties when you want to animate them separately

Remember this#

Transforms are like moving a sticker on glass — the page underneath does not change.

One transform property, many functions. Order matters (right to left).

Centre anything: top 50%, left 50%, translate(-50%, -50%).

Practice exercise#

Your task: Make an arrow icon (▶) rotate 90 degrees smoothly when its parent <details> is open.

Need a hint?
details[open] .arrow { transform: rotate(90deg) } with a transition on .arrow.
Show solution
HTML Runnable
<style>
  .arrow { display: inline-block; transition: transform 200ms; }
  details[open] .arrow { transform: rotate(90deg); }
  summary { list-style: none; cursor: pointer; }
</style>
<details><summary><span class="arrow">▶</span> More info</summary><p>Hidden content.</p></details>
Opens this example in the full playground

Mini quiz#

Transforms quizMultiple choice Question 1 of 3

Which transform makes an element 50% larger?

Score so far: 0/0

Want more? Practise all CSS MCQs · CSS interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.