I saw this animation on codepen, and I don't know why it's written this way to have this effect, but I think it's going to have the effect of rotating 360deg clockwise, 360deg counterclockwise, instead of bouncing up and down or left and right
I'm particularly puzzled with these Keyframe animation
@keyframes move{
from {
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
Results the following
https://i.stack.imgur.com/9oWnw.gif
From the specification we can see how the broswer should deal with interpolation between transform
values. In this case we use this:
If from- and to-transform have the same number of transform functions,
each transform function pair has either the same name, or is a
derivative of the same primitive: Interpolate each transform function
pair as described in Interpolation of transform functions. The
computed value is the resulting transform function list.
So the browser will change the first rotate
from 360deg
to -360deg
and the same for the last rotate
while translateX
will kept the same. We will then have the following steps:
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
transform: rotate(350deg) translateX(1.125em) rotate(-350deg);
transform: rotate(340deg) translateX(1.125em) rotate(-340deg);
....
transform: rotate(0) translateX(1.125em) rotate(0);
....
....
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
Now we need to understand how rotate(-adeg) translateX(b) rotate(adeg)
works. First you may notice that the rotation won't have any visual effect on the element since we deal with a circle, it will simply affect how the translation will work and more precisely it's the first rotation that is important (the one in the left).
.container {
width: 50px;
height: 50px;
margin: 50px;
border:2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
border-radius: 50%;
animation: move 2s linear infinite;
}
.alt {
animation: move-alt 2s linear infinite;
}
@keyframes move {
from {
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
@keyframes move-alt {
from {
transform: rotate(360deg) translateX(1.125em);
}
to {
transform: rotate(-360deg) translateX(1.125em);
}
}
<div class="container">
<div class="box">
</div>
</div>
<div class="container">
<div class="box alt">
</div>
</div>
As you can see both animation are equivalent visually.
Now the effect is as follow: each time we rotate the X-axis and then we translate our element consider the new rotated axis. It's like we rotate the coordinate system then we translate OR its like we do the translation once (since it's the same) then we keep rotating the coordinate system thus we have a rotation at the end.
Now if we consider the opposite transform nothing will happen visually:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
border-radius: 50%;
animation: move 2s linear infinite;
}
@keyframes move {
from {
transform: translateX(1.125em) rotate(-360deg);
}
to {
transform: translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
In this case we translate the coordinate system by the same translation then we rotate our circle. If we change it to a square we will see the effect
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s linear infinite;
}
@keyframes move {
from {
transform: translateX(1.125em) rotate(-360deg);
}
to {
transform: translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
And here is how your initial animation will look with a square:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s linear infinite;
}
@keyframes move {
from {
transform:rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform:rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
We rotate the coordinate system, we translate our element then we rotate the element so it's like we rotate our the element inside a bigger one that is also rotating in the opposite direction.
If you change the timing function to something else than linear you will have the same rotation but it won't be linear, it will be slower/faster in some interval:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s ease-in-out infinite;
}
@keyframes move {
from {
transform:rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform:rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
This is a simplified explanation, you may check this answer if you want more details about how we deal with multiple function inside transform and how the order is important: Simulating transform-origin using translate