Reputation: 181
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?
Upvotes: 8
Views: 3700
Reputation: 272592
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
Upvotes: 16