How They Fit Together: Transform, Translate, Rotate, Scale, and Offset

The transform property and its friends became more powerful through the addition of the new individual transform properties (translate, rotate, scale) and the offset properties (as a part of CSS Motion Path). All effectively provide a transformation for your element, and all have to follow specific rules to know how those transformations apply.

These new properties are now available in Firefox 72+. Motion path properties are also in Chromium browsers, and the independent transform properties are behind the Experimental Web Platform Features flag.

The power of the transform property is that it can hold any number of transformations. There can be multiple translations, rotations, scalings, skewings, and perspective changes. If you combine them in different orders, you can get different effects.

How do all these new properties interact with transform and transform-origin?

Basics of Transformations

When you perform transformations, you technically are not modifying the element itself. You are affecting its coordinate system. So a rotation rotates the x and y axes. If you have a transform that rotates 45 degrees and then apply a translate 100 pixels to the right, the translation will not go to the true right. It will instead go to the right of the already rotated coordinate system, so it will be going down and to the right at the 45 degree angle.

See the Pen Visual Reference: Transform Coordinate Systems by Dan Wilson (@danwilson) on CodePen.

What new options do the independent transform properties provide?

aside {
  rotate: 33deg;
  scale: .85;
  translate: 20px 50px;
}
aside.equivalent {
  transform: translate(20px, 50px) rotate(33deg) scale(.85);
}

Instead of always having everything inside the transform function, we can specify one translation, one rotation, and one scale separately. This can be cleaner or more readable for some codebases.

It also allows us to change one without overriding the other transformations.

aside {
  transform: rotate(10deg)
}
aside:hover {
  transform: scale(.85);
}

At first glance, you might expect this element to be rotated 10 degrees and then on hover add a scale down to the original transformation. But properties override, so the rotation is lost on hover. As different states or interactions become more complex it can be complicated to keep all the desired transformations straight.

But with the independent transform properties, we can add or remove individual transformations without affecting the others. So we can slightly alter our code and get a different result where the hover state is both rotated and scaled.

aside {
  rotate: 10deg
}
aside:hover {
  scale: .85;
}

We can also transition or animate each individually. In this example, the scale and translation change on hover with different durations and delays. The rotate does not transition but instead stays unaffected by the other two properties animating.

See the Pen Independent Transform Properties by Dan Wilson (@danwilson) on CodePen.

What are the limitations?

These properties do not take a list of options like the original transform property, so you only get one of each type per element. If you want more than that, you will need return to the transform.

They also all share the same transform-origin, so whether you are using the transform property or the three individual properties they all depend on transform-origin.

These properties are always applied in the same order, and they happen before everything in the transform property:

  1. translate
  2. rotate
  3. scale

See the Pen Visual Reference: Order of translate, rotate, scale by Dan Wilson (@danwilson) on CodePen.

If you want to have the rotation applied before a translation, you will need to use the transform property. Either of the following options would support this scenario.

aside {
  transform: rotate(30deg) translate(10px,10px);
}
/* These are still separate, so you still can work independently */
aside.alternate {
  rotate: 30deg;
  transform: translate(10px,10px)
}

Wait… why were the offset properties mentioned at the beginning?

With the transform property we can translate, rotate, scale, and skew our element as we choose, and the offset properties also effectively translate and rotate our element.

Even though it works in a different way, the offset properties all are effectively applying transformations on the coordinate system, in a similar manner to the transforms. As such, they also rely on the same transform-origin that the other four transformation properties use.

When are the offset properties applied?

The three new independent transform properties happen before the offset properties. The transform functions are applied in order after the offset.

  1. translate
  2. rotate
  3. scale
  4. offset (distance, anchor, and rotate)
  5. transform (functions applied in the order specified)

So for example, using a basic offset-path animation will produce a different visual result when you combine it with a transform: translate(25px -35px) versus combining it with a translate: 25px -35px.

See the Pen transform:translate vs translate with offset-path by Dan Wilson (@danwilson) on CodePen.

(I also have a rotate example with transform-origin thrown in for good measure if you so please).

It is certainly interesting (and often confusing) how these all interact with each other. Knowing the order of transformations, though, is at least half the struggle in clearing up some of the transformation magic happening with transform, independent transform properties, and Motion Path.