| |

Tailwind CSS 25 🎨 2D Transforms (Scale, Rotate, Translate, Skew, Origin)

A transform changes how an element is drawn without changing its position in the document flow. A scaled button is still the same size in the layout. A rotated card still occupies its original rectangle. A translated tooltip still reserves its original space. This separation between layout and rendering is what makes transforms powerful: they let you animate, emphasize, and reposition elements without triggering the layout recalculations that make animations expensive. Tailwind exposes the full set of 2D transforms as composable utilities, each one a single class.

This chapter covers the four 2D transform functions—scale, rotate, translate, and skew—along with transform-origin, which controls the point around which transforms are applied. You will learn the utility scales for each function, how transforms compose, how to use arbitrary values for custom transforms, and the properties of transforms that matter for animation and accessibility.

Key point: Transforms are applied in a specific order: translate, rotate, skew, then scale. Tailwind composes the transform value from CSS variables, so the order is fixed by the framework’s implementation, not by the order you write the classes. A transform does not affect layout, but it does affect the visual position of the element and its descendants.


Why transform utilities exist

The layout performance problem. Animating width, height, top, or left triggers the browser’s layout engine on every frame. Layout is expensive, and animations that trigger it can drop frames even on fast machines. Transforms are handled by the compositor, which runs on a separate thread and can animate without touching layout. This is why modern animation guidance consistently recommends transforms over positional properties for anything that moves .

The composition problem. A single element often needs multiple transforms: scaled up on hover, slightly rotated, shifted a few pixels. Writing the combined CSS by hand—transform: translateX(4px) rotate(3deg) scale(1.05)—is manageable but verbose, and changing one part requires editing the whole declaration. Tailwind’s transform utilities each set a separate CSS variable, and a single transform property references all of them. You can add, remove, or change one transform without touching the others.

The origin problem. A rotation or scale happens around a point called the transform origin. The default is the center of the element, which is correct for most cases. But a tooltip that scales from a corner, or a card that rotates around its bottom edge, needs a different origin. The origin-* utilities set this point without requiring custom CSS.

The reset problem. Transforms on a parent affect all children. A scaled parent scales its children too, which is sometimes desirable and sometimes not. Tailwind provides transform-none to remove all transforms, and transform-gpu to force GPU acceleration when needed. Understanding when to reset and when to leave transforms in place is part of using them well.

The accessibility problem. Motion can cause discomfort for users with vestibular disorders. Rotations, scales, and large translations are the most likely to trigger symptoms. Tailwind’s motion-reduce variant lets you disable transforms when the user has requested reduced motion, which is a requirement for accessible interfaces .


a. Scale, rotate, and translate

Scale changes the element’s size. The scale utilities set --tw-scale-x and --tw-scale-y, which the transform property reads.

<div class="scale-0">Invisible</div>
<div class="scale-50">Half size</div>
<div class="scale-75">75% size</div>
<div class="scale-90">90% size</div>
<div class="scale-95">95% size</div>
<div class="scale-100">Normal size</div>
<div class="scale-105">105% size</div>
<div class="scale-110">110% size</div>
<div class="scale-125">125% size</div>
<div class="scale-150">150% size</div>

Axis-specific scale uses scale-x-* and scale-y-*, which set only one of the two variables. Negative scale values flip the element: -scale-x-100 mirrors horizontally, -scale-y-100 mirrors vertically.

Rotate turns the element around its origin. The default scale runs in increments of 1, 2, 3, 6, 12, 45, 90, and 180 degrees.

<div class="rotate-0">No rotation</div>
<div class="rotate-1">1 degree</div>
<div class="rotate-3">3 degrees</div>
<div class="rotate-6">6 degrees</div>
<div class="rotate-12">12 degrees</div>
<div class="rotate-45">45 degrees</div>
<div class="rotate-90">90 degrees</div>
<div class="rotate-180">180 degrees</div>

Negative rotations use a leading dash: -rotate-45, -rotate-90. Arbitrary values are supported: rotate-[17deg], -rotate-[17deg]. The arbitrary value requires the unit—rotate-[17] without deg is invalid.

Translate moves the element along the x or y axis without affecting layout. The translate utilities set --tw-translate-x and --tw-translate-y.

<div class="translate-x-0">No horizontal shift</div>
<div class="translate-x-4">1rem right</div>
<div class="translate-x-1/2">50% right</div>
<div class="translate-y-4">1rem down</div>
<div class="translate-y-1/2">50% down</div>
<div class="-translate-y-4">1rem up</div>

The scale includes numeric values that map to the spacing scale, fractions like translate-x-1/2, and the keyword translate-x-full for 100% of the element’s width. Negative values use a leading dash.


b. Skew and transform origin

Skew slants the element along the x or y axis. It is the least commonly used of the four transforms, but it is useful for decorative effects and certain 3D-look designs.

<div class="skew-x-0">No skew</div>
<div class="skew-x-1">1 degree</div>
<div class="skew-x-3">3 degrees</div>
<div class="skew-x-6">6 degrees</div>
<div class="skew-x-12">12 degrees</div>
<div class="skew-y-3">Skew on Y axis</div>
<div class="-skew-x-6">Negative skew</div>

Skew has separate utilities for the x and y axes—skew-x-* and skew-y-*—but no shorthand that sets both. This is because skewing both axes simultaneously produces a different visual effect than most designs need.

Transform origin sets the point around which all transforms are applied. The default is center, which is correct for most scale and rotate operations.

<div class="origin-center">Center (default)</div>
<div class="origin-top">Top center</div>
<div class="origin-top-right">Top right</div>
<div class="origin-right">Right center</div>
<div class="origin-bottom-right">Bottom right</div>
<div class="origin-bottom">Bottom center</div>
<div class="origin-bottom-left">Bottom left</div>
<div class="origin-left">Left center</div>
<div class="origin-top-left">Top left</div>

The origin matters most for rotation and scale. A tooltip that scales from its top-left corner uses origin-top-left. A card that rotates around its bottom edge uses origin-bottom. Without the right origin, the transform produces the wrong motion.


c. Composing transforms and GPU acceleration

Transforms compose. An element can be scaled, rotated, and translated at the same time.

<div class="scale-110 rotate-3 translate-y-2">Multiple transforms</div>

Tailwind applies them in a fixed order: translate, rotate, skew, then scale. This order is defined by the CSS variable composition in the transform property, not by the order of the classes in the HTML. If you need a different order, you must write a custom transform with arbitrary values.

The transform utility enables the transform property without changing any of the variables. This is the base class that all transform utilities depend on. In modern Tailwind, the transform utilities include the transform property themselves, so a bare transform class is rarely needed.

GPU acceleration is controlled with transform-gpu. This forces the browser to promote the element to its own compositor layer, which can improve animation performance but uses more memory. Use it sparingly.

<div class="transform-gpu scale-110">GPU-accelerated</div>

Resetting transforms is done with transform-none, which removes all transforms from the element. This is useful when a parent has a transform that should not apply to a child, or when a transform should be removed on hover.

<div class="scale-110 hover:transform-none">
  Scales by default, no scale on hover
</div>

Transforms respond to variants: hover:scale-105, focus:rotate-2, active:scale-95, group-hover:translate-x-1. This makes them ideal for interactive feedback: a button that grows slightly on hover, a card that lifts on focus, an icon that rotates on click.

Accessibility is handled with the motion-reduce variant. Combine it with motion-safe to provide a fallback for users who have not requested reduced motion.

<div class="transition-transform hover:scale-110 motion-reduce:transform-none">
  Scales on hover unless reduced motion is preferred
</div>

The motion-reduce:transform-none class disables the scale when the user has set prefers-reduced-motion: reduce. This is a small addition with a meaningful impact for users with vestibular disorders .


Complete Example Session

<!-- ============================================ -->
<!-- PART 1: SCALE -->
<!-- ============================================ -->
<div class="scale-50 bg-blue-500 p-4">50%</div>
<div class="scale-100 bg-blue-500 p-4">100%</div>
<div class="scale-150 bg-blue-500 p-4">150%</div>
<!-- ============================================ -->
<!-- PART 2: AXIS-SPECIFIC SCALE -->
<!-- ============================================ -->
<div class="scale-x-150 bg-blue-500 p-4">Wide</div>
<div class="scale-y-150 bg-blue-500 p-4">Tall</div>
<div class="-scale-x-100 bg-blue-500 p-4">Mirrored</div>
<!-- ============================================ -->
<!-- PART 3: ROTATE -->
<!-- ============================================ -->
<div class="rotate-0 bg-green-500 p-4">0deg</div>
<div class="rotate-45 bg-green-500 p-4">45deg</div>
<div class="rotate-90 bg-green-500 p-4">90deg</div>
<div class="rotate-180 bg-green-500 p-4">180deg</div>
<div class="-rotate-12 bg-green-500 p-4">-12deg</div>
<!-- ============================================ -->
<!-- PART 4: TRANSLATE -->
<!-- ============================================ -->
<div class="translate-x-4 bg-purple-500 p-4">Right 1rem</div>
<div class="translate-y-4 bg-purple-500 p-4">Down 1rem</div>
<div class="-translate-x-4 bg-purple-500 p-4">Left 1rem</div>
<div class="translate-x-1/2 bg-purple-500 p-4">50% right</div>
<!-- ============================================ -->
<!-- PART 5: SKEW -->
<!-- ============================================ -->
<div class="skew-x-0 bg-amber-500 p-4">No skew</div>
<div class="skew-x-6 bg-amber-500 p-4">Skew X 6</div>
<div class="skew-y-6 bg-amber-500 p-4">Skew Y 6</div>
<div class="-skew-x-12 bg-amber-500 p-4">Negative skew</div>
<!-- ============================================ -->
<!-- PART 6: TRANSFORM ORIGIN -->
<!-- ============================================ -->
<div class="origin-top-left rotate-45 bg-pink-500 p-4">Top left</div>
<div class="origin-bottom-right rotate-45 bg-pink-500 p-4">Bottom right</div>
<div class="origin-center rotate-45 bg-pink-500 p-4">Center</div>
<!-- ============================================ -->
<!-- PART 7: COMPOSED TRANSFORMS -->
<!-- ============================================ -->
<div class="scale-110 rotate-3 translate-y-2 bg-indigo-500 p-4">
  Scale + rotate + translate
</div>
<!-- ============================================ -->
<!-- PART 8: HOVER TRANSFORMS WITH TRANSITION -->
<!-- ============================================ -->
<button class="bg-cyan-500 p-4 transition-transform hover:scale-105">
  Hover to scale
</button>
<button class="bg-cyan-500 p-4 transition-transform hover:rotate-3">
  Hover to rotate
</button>
<button class="bg-cyan-500 p-4 transition-transform hover:-translate-y-1">
  Hover to lift
</button>
<!-- ============================================ -->
<!-- PART 9: GPU ACCELERATION -->
<!-- ============================================ -->
<div class="transform-gpu scale-110 transition-transform">
  GPU-accelerated
</div>
<!-- ============================================ -->
<!-- PART 10: REDUCED MOTION -->
<!-- ============================================ -->
<button class="
  transition-transform
  hover:scale-110
  motion-reduce:transform-none
">
  Accessible hover
</button>

The ten parts covered scale, axis-specific scale, rotate, translate, skew, transform origin, composed transforms, hover transforms with transitions, GPU acceleration, and reduced motion support.


Quick Reference

Scale Utilities

ClassEffect
scale-0scale: 0
scale-50scale: 0.5
scale-75scale: 0.75
scale-90scale: 0.9
scale-95scale: 0.95
scale-100scale: 1
scale-105scale: 1.05
scale-110scale: 1.1
scale-125scale: 1.25
scale-150scale: 1.5
scale-x-{n}Scale X only
scale-y-{n}Scale Y only

Rotate Utilities

ClassEffect
rotate-00deg
rotate-11deg
rotate-22deg
rotate-33deg
rotate-66deg
rotate-1212deg
rotate-4545deg
rotate-9090deg
rotate-180180deg
-rotate-{n}Negative rotation
rotate-[17deg]Arbitrary value

Translate Utilities

ClassEffect
translate-x-{n}Horizontal shift
translate-y-{n}Vertical shift
translate-x-1/250% horizontal
translate-y-full100% vertical
-translate-{axis}-{n}Negative shift

Transform Origin

ClassEffect
origin-centerCenter (default)
origin-topTop center
origin-top-rightTop right
origin-rightRight center
origin-bottom-rightBottom right
origin-bottomBottom center
origin-bottom-leftBottom left
origin-leftLeft center
origin-top-leftTop left

Transform Modifiers

ClassEffect
transform-gpuForce GPU acceleration
transform-noneRemove all transforms
transition-transformAnimate transform changes
motion-reduce:transform-noneDisable for reduced motion

Best Practices

✅ Do This:

<!-- Use transforms for animation instead of layout properties -->
<button class="hover:scale-105 transition-transform">Save</button> <!-- ✅ -->

<!-- Set origin for rotation and scale -->
<div class="origin-top-left rotate-45">Tooltip</div>               <!-- ✅ -->

<!-- Use motion-reduce for accessibility -->
<button class="hover:scale-110 motion-reduce:transform-none">      <!-- ✅ -->

<!-- Use translate for positioning without layout shift -->
<div class="translate-y-1/2">Overlay</div>                         <!-- ✅ -->

<!-- Compose transforms for complex effects -->
<div class="scale-110 rotate-3 translate-y-2">Card</div>           <!-- ✅ -->

<!-- Use GPU acceleration sparingly -->
<div class="transform-gpu transition-transform">Animated</div>     <!-- ✅ -->

❌ Don’t Do This:

<!-- Don't animate layout properties for movement -->
<div class="hover:mt-4 transition-all">Bad</div>                   <!-- ❌ -->

<!-- Don't forget the unit in arbitrary rotate values -->
<div class="rotate-[17]">Invalid</div>                             <!-- ❌ -->

<!-- Don't use transform-gpu everywhere -->
<div class="transform-gpu">Every element</div>                     <!-- ❌ memory cost -->

<!-- Don't scale without checking overflow -->
<div class="scale-150">Clipped content</div>                       <!-- ⚠️ -->

<!-- Don't forget motion-reduce for large motion -->
<div class="rotate-180 transition-transform">                      <!-- ⚠️ -->

Common Pitfalls

PitfallWhy It HappensFix
Transform doesn’t applyNo transform propertyAdd a transform utility
Rotation around wrong pointDefault origin is centerSet origin-*
Arbitrary rotate ignoredMissing deg unitUse rotate-[17deg]
Children also scaledTransform affects subtreeReset child with transform-none
Animation jankyLayout property animatedUse transform instead
GPU memory highToo many transform-gpuUse sparingly
Motion sicknessNo reduced-motion fallbackAdd motion-reduce:transform-none

Real-World Examples

1. Button Hover Scale

<button class="transition-transform hover:scale-105">Click</button>

2. Card Lift on Hover

<div class="transition-transform hover:-translate-y-1 hover:shadow-lg">

3. Icon Rotate on Expand

<svg class="transition-transform group-open:rotate-180">...</svg>

4. Tooltip Scale from Corner

<div class="origin-top-left scale-0 group-hover:scale-100 transition-transform">

5. Modal Entry Animation

<div class="scale-95 opacity-0 transition-all data-open:scale-100 data-open:opacity-100">

6. Loading Spinner

<div class="animate-spin">⟳</div>

7. Notification Badge Pulse

<span class="scale-100 animate-pulse">3</span>

8. Mirror Image

<img class="-scale-x-100" src="arrow.svg" />

9. Skewed Accent

<div class="skew-x-12 bg-blue-500 p-2 text-white">Accent</div>

10. Accessible Hover Effect

<button class="hover:scale-110 transition-transform motion-reduce:transform-none">

Visual

Transform Functions

┌─────────────────────────────────────────────────────────────┐
│  SCALE                                                      │
│  ┌─────────┐      ┌─────────────┐                           │
│  │ Element │ ──▶  │   Element   │  (larger, same position)  │
│  └─────────┘      └─────────────┘                           │
│                                                             │
│  ROTATE                                                     │
│  ┌─────────┐      ┌─────────┐                               │
│  │ Element │ ──▶  │  ╱      │  (turned around origin)       │
│  └─────────┘      │ ╱       │                               │
│                   └─────────┘                               │
│                                                             │
│  TRANSLATE                                                  │
│  ┌─────────┐                                                 │
│  │ Element │ ──▶      ┌─────────┐                            │
│  └─────────┘          │ Element │  (moved, layout unchanged) │
│                       └─────────┘                            │
│                                                             │
│  SKEW                                                       │
│  ┌─────────┐      ┌───────────┐                             │
│  │ Element │ ──▶  │  Element  │  (slanted)                  │
│  └─────────┘      └───────────┘                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Transform Origin Effect

┌─────────────────────────────────────────────────────────────┐
│  ROTATE WITH DIFFERENT ORIGINS                              │
│                                                             │
│  origin-center:                                             │
│  ┌─────────┐      ┌─────────┐                               │
│  │    ●    │ ──▶  │   ╱     │  Rotates around middle        │
│  │ Element │      │  ╱      │                               │
│  └─────────┘      └─────────┘                               │
│                                                             │
│  origin-top-left:                                           │
│  ●─────────┐      ●─────────┐                               │
│  │ Element │ ──▶  │╲        │  Rotates around top-left      │
│  └─────────┘      │ ╲       │                               │
│                   └─────────┘                               │
│                                                             │
│  origin-bottom:                                             │
│  ┌─────────┐      ┌─────────┐                               │
│  │ Element │ ──▶  │╲       ╱│  Rotates around bottom        │
│  └────●────┘      └─────────┘                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Transform Order

┌─────────────────────────────────────────────────────────────┐
│  TAILWIND TRANSFORM COMPOSITION ORDER                       │
│                                                             │
│  CSS output:                                                │
│  transform:                                                 │
│    translate(var(--tw-translate-x), var(--tw-translate-y))  │
│    rotate(var(--tw-rotate))                                 │
│    skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))          │
│    scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));     │
│                                                             │
│  Order is fixed: translate → rotate → skew → scale          │
│  Class order in HTML does not change this.                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Layout vs Transform

┌─────────────────────────────────────────────────────────────┐
│  LAYOUT PROPERTY (Expensive)                                │
│                                                             │
│  Changing margin-top:                                       │
│  ┌─────────┐                                                │
│  │ Element │  ──▶  Recalculate layout, repaint, composite   │
│  └─────────┘                                                │
│                                                             │
│  Affects surrounding elements. Triggers layout engine.      │
│                                                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  TRANSFORM (Cheap)                                          │
│                                                             │
│  Changing translate-y:                                      │
│  ┌─────────┐                                                │
│  │ Element │  ──▶  Composite only (no layout, no paint)     │
│  └─────────┘                                                │
│                                                             │
│  Does not affect surrounding elements. Runs on compositor.  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Summary

ItemValue
Scalescale-{0-150}, scale-x-*, scale-y-*
Rotaterotate-{0-180}, negative with -
Translatetranslate-x-*, translate-y-*, fractions
Skewskew-x-*, skew-y-*
Originorigin-{center,top,right,bottom,left,corners}
Composition ordertranslate → rotate → skew → scale
GPUtransform-gpu
Resettransform-none
Transitiontransition-transform
Accessibilitymotion-reduce:transform-none
Arbitrary valuesrotate-[17deg], scale-[1.15]

Key takeaways:

  • Transforms do not affect layout. A scaled or rotated element occupies its original space in the document flow. This is what makes transforms efficient for animation.
  • Transforms compose in a fixed order. Tailwind applies translate, then rotate, then skew, then scale. The order of classes in the HTML does not change this. For a custom order, use arbitrary values.
  • Transform origin controls the pivot point. The default is center. Rotation and scale around a corner or edge require setting origin-*. This is the difference between a tooltip that grows from its corner and one that grows from its middle.
  • Arbitrary rotate values require units. rotate-[17deg] is valid; rotate-[17] is not. The unit is part of the CSS value.
  • Use transforms for movement, not layout properties. Animating margin, top, or width triggers layout. Animating transform does not. This is the single most important performance consideration for animation.
  • GPU acceleration has a cost. transform-gpu promotes the element to its own compositor layer, which uses memory. Use it for animated elements, not for every element.
  • Reduced motion is a requirement, not a nicety. Large rotations, scales, and translations can cause discomfort. motion-reduce:transform-none disables the transform when the user has requested reduced motion.
  • Transforms apply to descendants. A scaled parent scales its children. Use transform-none on a child to reset its transform within a transformed parent.

Remember: Transforms are the modern way to move and animate elements. They change how an element is drawn without changing where it sits in the layout, which makes them fast and predictable. Tailwind exposes the four 2D transforms—scale, rotate, translate, and skew—as composable utilities backed by CSS variables. The order of composition is fixed, so the transforms combine predictably. Set the origin deliberately, use transitions for interaction feedback, and always provide a reduced-motion fallback for large motion. Transforms are cheap to render but easy to overuse; apply them where they add meaning, not decoration.



Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!