Simulating transform-origin using translate

You are almost good but you have two errors. You need to invert the translations and you need to change the transform-origin of the second one.

If you check the documentation, you will see that the reference used to translate the origin is the top left corner of the element and the default value of transform origin is center. So we need to have the same reference for both.

.origin {
  transform-origin: 50px 50px;
  transform:  rotate(45deg) scale(2);
}
.translate {
  transform-origin:0 0; 
  transform:translate(50px, 50px) rotate(45deg) scale(2) translate(-50px, -50px);
} 
.box {
  background-color: red;
  width: 50px;
  height: 50px;
}
.container {
  display: inline-block;
  margin: 30px;
  width: 150px;
  height: 150px;
  background-color: rgba(0,0,0,0.1);
}
<div class="container">
  <div class="box origin">
  </div>
</div>
<div class="container">
  <div class="box translate">
  </div>
</div>

Here is from the specification:

The transformation matrix is computed from the transform and
transform-origin properties as follows:

  1. Start with the identity matrix.

  2. Translate by the computed X and Y of transform-origin

  3. Multiply by each of the transform functions in transform property from
    left to right

  4. Translate by the negated computed X and Y values of transform-origin

You need to pay attention to the wording! You may find that the MDN is contradictory with the specification BUT it’s not the case simply because there is a difference between translating the element (like described in the MDN) and translating the origin of the element or the local coordinate (like described in the specification).

For example, translating the element by -50px is equivalent to translating its local coordinate (origin) by +50px.


You need to also pay attention to the “Multiply from left to right” as it may create confusion. If we refer to the same specification in the Example 3 we have:

div {
  height: 100px; width: 100px;
  transform: translate(80px, 80px) scale(1.5, 1.5) rotate(45deg);
}

This transformation translates the local coordinate system by 80
pixels in both the X and Y directions, then applies a 150% scale, then
a 45° clockwise rotation about the Z axis. The impact on the
rendering of the element can be intepreted as an application of these
transforms in reverse order
: the elements is rotated, then scaled,
then translated.

So multiplying from left to right doesn’t mean applying from left to right which somehow explain the need of inverting the translation you applied to simulate the transform-origin:

Leave a Comment