I have a div of 6400x3600 size. I'm using transform-origin: 50% 50%. When I set the scale to 0.9, for the children to stay on the top left corner I need to translate to a negative value. My reasoning was 6400 - 5760(90%) = 640 / 2 = 320... so for x it should translate -320px.. but actually what is needed is -355.556px.
Example: https://jsfiddle.net/fvnq3ewj/28/
* {
padding: 0;
margin: 0;
}
.container {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 6400px;
height: 3600px;
background-color: red;
transform-origin: 50% 50%;
transform: scale(0.9) translate(-355.556px, -200px);
}
<html>
<body>
<div class="container">
</div>
</body>
</html>
Someone have any explanation for this?
Since the translation is done after the scale()
it will also get scaled so your 320px
need to be divided by 0.9
to get the correct value:
320/0.9 = 355.56
In other words, you need to move by 355.56px
to actually get the 320px
. It's a bit tricky but imagine your self inside another world scaled by 0.9
. The perception of the distances outside that world will not be the same inside the scaled world.
A related question to get more details about the math: Why does order of transforms matter? rotate/scale doesn't give the same result as scale/rotate
In your case:
scale(0.9) translate(A, B)
Is equivalent to:
|0.9 0 0| |1 0 A| |0.9 0 A*0.9|
|0 0.9 0| x |0 1 B| = |0 0.9 B*0.9|
|0 0 1| |0 0 1| |0 0 1 |
So
Xf = 0.9*(Xi + A);
Yf = 0.9*(Yi + B);
If you do the opposite (translate then scale) you can use 320px
* {
padding: 0;
margin: 0;
}
.container {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 6400px;
height: 3600px;
background-color: red;
transform-origin: 50% 50%;
transform: translate(-320px, -180px) scale(0.9) ;
}
<div class="container">
</div>
The math will be:
|1 0 A| |0.9 0 0| |0.9 0 A|
|0 1 B| x |0 0.9 0| = |0 0.9 B|
|0 0 1| |0 0 1| |0 0 1|
Xf = 0.9*Xi + A;
Yf = 0.9*Yi + B;
Note how the translation values are not affected by the scale factor
If you want to go more in depth we consider the transform-origin
to get the full formula. Here is a related question: Simulating transform-origin using translate
So the full matrix multiplication will become:
|1 0 50%| |0.9 0 0| |1 0 A| |1 0 -50%|
|0 1 50%| x |0 0.9 0| x |0 1 B| x |0 1 -50%|
|0 0 1 | |0 0 1| |0 0 1| |0 0 1 |
We will get:
Xf = 0.9*Xi + 0.9*(A - 50%) + 50%;
Yf = 0.9*Yi + 0.9*(B - 50%) + 50%;
We need to keep the element on the top left so for (Xi,Yi) = (0,0)
we need to also get (Xf,Yf) = (0,0)
0 = 0.9*(A - 50%) + 50%;
A = 50%*(0.9 - 1)/0.9
A = 50%*-0.111111
And 50% = 6400px/2 = 3200px
then A = -355.52px
Same logic for B
to get -200px
For the opposite order we will have:
Xf = 0.9*Xi - 0.9*50% + A + 50%;
Yf = 0.9*Yi - 0.9*50% + B + 50%;
A = (0.9 - 1)*50% = -320px
B = -180px