Given this code (http://jsfiddle.net/bzf1mkx5/)
Let's first understand what reverse
mean
The animation plays backwards each cycle. In other words, each time the animation cycles, the animation will reset to the end state and start over again. Animation steps are performed backwards, and timing functions are also reversed. For example, an ease-in timing function becomes ease-out. ref
Let's take a basic example to understand:
.box {
width:50px;
height:50px;
margin:5px;
background:red;
position:relative;
}
.normal {
animation: move normal 2s linear forwards;
}
.reverse {
animation: move reverse 2s linear forwards;
}
@keyframes move{
from {
left:0;
}
to {
left:300px;
}
}
<div class="box normal">
</div>
<div class="box reverse">
</div>
We have one animation and the first element is runnig it forwards while the second element is running it backwards. Technically, it's like we invert the from
and to
. reverse
is useful in order to avoid defining a new animation in the opposite direction. We define a left-to-right animation and with reverse we have the right-to-left one. Until now, it's trivial.
Now, if you run any kind of animation defined by its name and in the road you modify a property of this animation you will change the behavior of the whole animation and we calculate again the value of the current state based on the new animation.
Example:
.box {
width:50px;
height:30px;
margin:5px;
background:red;
position:relative;
}
.normal,
.special{
animation: move normal 20s linear forwards;
background:blue;
}
.reverse,
div:hover .special{
animation: move reverse 20s linear forwards;
background:green;
}
@keyframes move{
from {
left:0;
}
to {
left:300px;
}
}
p {
margin:0;
}
<p>Reference</p>
<div class="box normal"></div>
<div class="box reverse"></div>
<p>Hover the element</p>
<div>
<div class="box special"></div>
</div>
We have 3 elements animating using the same animation at the same time so they will all be at the same progress. The third one is the same as the first animation and on hover it become the same as the second one. The trick is here! on hover you will not consider the actual position of the element and simply move in the other direction but you will consider the new animation defined by reverse
and calculate the value of left considering the actual progress of the animation.
If the element is at 5s
of the animation in the normal state we will have left:100px
and in the reverse state we will have left:200px
so if you hover at 5s
you will toggle between 100px
and 200px
. You will not consider left:100px
and move back to the 0px
Now it clear that if the animation is over, you will simply toggle between the first and the last state. You will not trigger a new animation again since we are dealing with the same animation and we simply changed one setting (the direction)
.box {
width:50px;
height:30px;
margin:5px;
background:red;
position:relative;
}
.normal,
.special{
animation: move normal 1s linear forwards;
background:blue;
}
.reverse,
div:hover .special{
animation: move reverse 1s linear forwards;
background:green;
}
@keyframes move{
from {
left:0;
}
to {
left:300px;
}
}
p {
margin:0;
}
<p>Reference</p>
<div class="box normal"></div>
<div class="box reverse"></div>
<p>Hover the element</p>
<div>
<div class="box special"></div>
</div>
Same logic happen if you change any other property. You will not see an intuitive result because you need to imagine how the new animation will be in order to identify how the current state will become.
Example if we change the timing-function
.box {
width:50px;
height:30px;
margin:5px;
background:red;
position:relative;
}
.normal,
.special{
animation: move 20s linear forwards;
background:blue;
}
.reverse,
div:hover .special{
animation: move 20s ease forwards;
background:green;
}
@keyframes move{
from {
left:0;
}
to {
left:300px;
}
}
p {
margin:0;
}
<p>Reference</p>
<div class="box normal"></div>
<div class="box reverse"></div>
<p>Hover the element</p>
<div>
<div class="box special"></div>
</div>
Example if we change the duration:
.box {
width:50px;
height:30px;
margin:5px;
background:red;
position:relative;
}
.normal,
.special{
animation: move 20s linear forwards;
background:blue;
}
.reverse,
div:hover .special{
animation: move 30s linear forwards;
background:green;
}
@keyframes move{
from {
left:0;
}
to {
left:300px;
}
}
p {
margin:0;
}
<p>Reference</p>
<div class="box normal"></div>
<div class="box reverse"></div>
<p>Hover the element</p>
<div>
<div class="box special"></div>
</div>
What you are looking for can be achieved with transition
because transition will only care about the current value and will transition to a new one when you want (on hover for example)
.intern {
width: 100px;
height: 100px;
margin:50px;
background-color: red;
transition:10s all;
}
.intern:hover {
transform:scale(4);
}
<div style="" class="intern"></div>
When you hover you will start a scale animation that will last 10s
BUT if you unhover before you will get back to the initial state. You cannot do this with animation. An animation need to either run fully or you abruptly cancel it in the middle and you get back to initial state
Even if you define two animation you will not always have the needed result in you hover when the running one is not yet over. You will cancel it and run the new one.
.intern {
width: 100px;
height: 100px;
margin:50px;
background-color: red;
animation:in 5s linear forwards;
}
.intern:hover {
animation:out 5s linear forwards;
}
@keyframes in {
from {
transform:scale(1);
}
to {
transform:scale(4);
}
}
@keyframes out {
from {
transform:scale(4);
}
to {
transform:scale(1);
}
}
<div style="" class="intern"></div>
Try to hover/unhover rapidly and you will see the bad effect. You will only have a perfect result if you hover at the end of each animation.
You have to set the transform
as a property as well:
.intern {
-webkit-transform: scale(1);
-webkit-animation: in 1s infinite reverse forwards;
}
.intern:hover {
-webkit-animation: in 1s infinite normal forwards;
}
@-webkit-keyframes in {
from {
-webkit-transform: scale(1);
}
to {
-webkit-transform: scale(1.2);
}
}
<div style="width : 100px; height : 100px; background-color : red" class="intern"></div>
Edit: To have a simple effect, you can use transitions instead of keyframes.
.intern {
width: 100px;
height: 100px;
background-color: red;
transform: scale(1);
transition: transform 1s;
}
.intern:hover {
transform: scale(1.2);
}
<div class="intern"></div>