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:
translate
rotate
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
.
translate
rotate
scale
offset
(distance, anchor, and rotate)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.