← all topics

Individual Transform Properties

CSS

CSS Transforms Level 2 introduced rotate, scale, and translate as standalone properties. Unlike the transform shorthand, they each live in their own cascade slot — hover the spinning elements to see what that means in practice.

Individual Properties

rotate and scale are independent — hover scales without breaking the spin

hover me
@keyframes spin {
  to { rotate: 360deg; }
}

.element {
  animation: spin 2s linear infinite;
  transition: scale 0.25s ease;
}

.element:hover {
  scale: 1.4; /* ✓ doesn't break spin */
}

Transform Shorthand

hover overwrites the entire transform value — the spin breaks on hover

hover me
@keyframes spin {
  to { transform: rotate(360deg); }
}

.element {
  animation: spin 2s linear infinite;
  transition: transform 0.25s ease;
}

.element:hover {
  /* ✗ replaces the animation's transform */
  transform: scale(1.4);
}

concepts

non-clobbering

Individual properties (rotate, scale, translate) each occupy a separate slot in the cascade. Setting one does not reset the others — unlike the transform shorthand, where any new value replaces the entire list.

fixed application order

The browser always applies them translate → rotate → scale, regardless of their declaration order in your CSS. This is equivalent to transform: translate() rotate() scale().

composable animations

Two independent animations targeting separate properties (say, a continuous spin and a hover scale) can run simultaneously on the same element. With the transform shorthand, they'd fight over the same property and one would win.

browser support

Broadly supported since 2022 — Chrome 104, Safari 14.1, Firefox 72. Safe for production.

core pattern

/* Each is an independent CSS property */
translate: 50px 20px;
rotate: 45deg;
scale: 1.5;

/* Fixed order: translate → rotate → scale */
/* Equivalent shorthand: */
transform: translate(50px, 20px) rotate(45deg) scale(1.5);

/* Two animations, no conflict */
@keyframes spin   { to { rotate: 360deg; } }
@keyframes bounce { 50% { translate: 0px -20px; } }

.element {
  animation:
    spin   2s linear    infinite,
    bounce 1s ease-in-out infinite;
}