Slowing rotation to a stop upon hover - css

Right now the 'box' immediately stops spinning upon mouse hover. How can this code be modified to have the box spin down gradually to a stop instead of immediately?
I've tried 'ease-in', etc, but obviously that would just cause the animation to iteratively ease in over and over again at each iteration instead of staying at the max speed indefinitely.
div.box{
border: 6px solid black;
background-color: blue;
width: 100px;
height: 100px;
animation: turnright 2s linear 0s infinite normal;
}
div.boxcontainer{
display: flex;
width: 112px;
height: auto;
border: 6px solid red;
animation: turnright 2s linear 0s infinite reverse forwards;
animation-play-state: paused;
&:hover{
animation-play-state: running;
}
}
#keyframes turnright{
0%{
rotate: 0deg;
}
100%{
rotate:360deg;
}
}
<div class='boxcontainer'>
<div class='box'/>
</div>
I've incorporated some ideas from : Smoothly Reverting Animation

Related

How do I freeze an animation in CSS?

I want the keyframe "smoothly" to do its thing when the button is hovered over.
It works great, but when the animation restarts, I want it to freeze at the end.
I have looked at some places, but I can't find anything that solves my problem.
My code:
#en {
display: inline-block;
padding: 0.3em 1.2em;
border:0.16em solid rgba(255,255,255,0);
font-weight: 300;
border-radius: 0em;
border-color: #4ef18f;
background-color: #4ef18f;
}
#keyframes smoothly {
from {background-color: #43f18f;}
to {background-color: #bbecd0;}
from {border-radius: 0em;}
to {border-radius: 4em;}
}
#en:hover {
animation-name: smoothly;
animation-duration: 1s;
}
Add animation: smoothly 1s forwards
Older browsers : -webkit-animation: smoothly 1s forwards;

Is it possible to play an animation in both directions with a single #keyframes rule?

I would like to use a single #keyframes rule to animate an element from one state to another and then to get back to the original state when I do an action (with the same animation). I saw that using animation-direction: reverse; is a way to play the animation in reverse. However, when I try to use it, the transitions on my element disappear. If I set a new #keyframes with the reversed state it works fine.
What is the point of animation-direction in this case? I am misunderstanding something?
Is there a way to play an animation in both directions with a single #keyframes rule without loosing the transitions? I can't use transition, I need animation.
Here is a example to play with (hover the squares):
div {
width: 100px;
height: 100px;
animation: fade 0.6s ease-in-out forwards;
margin: 15px;
display: inline-flex;
align-items: center;
justify-content: center;
color: white;
}
#box-1:hover {
animation: fade 0.6s ease-in-out forwards;
animation-direction: reverse;
}
#box-2:hover {
animation: fadeReverse 0.6s ease-in-out forwards;
}
#keyframes fade {
0% { background: red; }
100% { background: blue; }
}
#keyframes fadeReverse {
0% { background: blue; }
100% { background: red; }
}
<div id="box-1">:(</div>
<div id="box-2">:)</div>
It's because you apply the same animation to the element on hover as the animation that is on the default state of the element.
So the element already had that animation with the default direction but then you apply it again with the reverse. But it won't work. I don't really know why this happens. But applying the same animation on an element twice, won't work. So you need 2 different keyframes.
You can use a reverse animation or duplicate the existing one and use it with direction: reverse
Read more here
restart animation
more info here
another article here
If you REALLY want to use just 1 animation this can be solved with javascript by removing and adding an 'animate-me' class . But it still wouldn't be ideal
div {
width: 100px;
height: 100px;
animation: fade 0.6s ease-in-out forwards;
margin: 15px;
display: inline-flex;
align-items: center;
justify-content: center;
color: white;
}
#box-1:hover {
animation: fade2 0.6s ease-in-out forwards;
animation-direction: reverse;
}
#box-2:hover {
animation: fadeReverse 0.6s ease-in-out forwards;
}
#keyframes fade {
0% { background: red; }
100% { background: blue; }
}
#keyframes fade2 {
0% { background: red; }
100% { background: blue; }
}
#keyframes fadeReverse {
0% { background: blue; }
100% { background: red; }
}
<div id="box-1">:(</div>
<div id="box-2">:)</div>

Smoothly transition from midway through CSS animation to start (or end)

I have a box that spins on click:
.box{
width: 200px;
height: 200px;
background:red;
transition: all 1s;
}
.box.spin{
animation: spin 5s infinite linear;
}
When you click it a second time, I'd like it to either unspin, or complete its spin to come to a halt. It seems that instead it snaps immediately back to its starting position:
https://codepen.io/EightArmsHQ/pen/OaoPKm?editors=0100
Is there a way of achieving this without replacing the animation with a transition?
What about use animation-play-state property ?
.box{
animation: spin 5s infinite linear; // add this here
animation-play-state: paused; // pause animation by default
}
.box.spin{
animation-play-state: running; // play animation
}
https://codepen.io/frantisekvrab/pen/YROXaZ
If you like to complete the spin, I assume you have to use some more JS or CSS transition.
By "unspin" do you mean to have it spin in the other direction? If so, you can do something like this:
window.onload = ()=>{
let box = document.querySelector('.box');
box.addEventListener('click', function(){
this.classList.toggle('spin')
this.classList.toggle('spin-reverse')
});
}
#keyframes spin{
0%{
transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
}
}
html, body{
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.box{
cursor: pointer;
width: 200px;
height: 200px;
background:red;
transition: all 1s;
box-sizing: border-box;
color: #fff;
display: flex;
padding: 30px;
text-align: center;
align-items: center;
justify-content: center;
user-select: none;
}
.box.spin{
animation: spin 5s infinite linear;
}
.box.spin-reverse {
animation: spin 5s infinite linear reverse;
}
<div class="box spin" id="box">
Click to toggle animation
</div>
Also, here's a working example :)

why isnt the css animation backwards argument working?

I have a simplw div that expands and changes colors, from my understanding the backwards value for the animation-fill-mode should reset the div to the first frame of the animation after it ends, including delays, I have a delay of zero ms and instead of resetting back to the first frame, it simply disappears, why?
//css
#keyframes frames{
from{
background-color: blue;
width: 50px;
height: 50px;
}
to{
background-color: orange;
width: 200px;
height: 200px;
}
}
#d1{
width: 50px;
height: 50px;
animation: frames 1000ms ease-in-out 0ms 3 alternate backwards;
}
//html
<div id="d1"></div>
Alternate backwards doesn't exist. You should use alternate-reverse:
#d1 {
width: 50px;
height: 50px;
animation: frames 1000ms ease-in-out 0ms 3 alternate-reverse;
}

CSS3 animate color by steps

I am trying to make an animation on a button which change the color and background-color from white to black.
I don't want any fade and so I found that I can use animation-timing-function: step.
However when I use it the animation doesn't reach black, it stops at grey.
.animated-play-btn {
background-color: white;
height: 50px;
width: 200px;
animation-timing-function: steps(2, end);
animation-duration: 1s;
animation-name: clipping_btn;
animation-iteration-count: infinite;
animation-fill-mode: forwards;
}
#keyframes clipping_btn {
from {
background-color: #000;
color: white;
}
to {
color: black;
background-color: #fff;
}
}
<button class="animated-play-btn">
coucou
</button>
Here the demo.
Any one have an idea how to do this (no JS of course)?
This seems to be sort of a "grey" area (pun intended) with respect to the steps() timing function for animations.
What seems to happen is that when you use steps(2, end), the animation is supposed to have two steps - one is from black background + white color to an intermediate state (where both are gray) and then another from the intermediate state to white background + black color (the end state) but the 2nd step happens right at the end of the animation and at almost the same time that the element is going to its original state to start the next loop. So, it kind of creates an impression that the white background + black color never happens.
The solution that seems to be working is to use steps(1, end) with the start and end states as black background + white color while the half way stage is white background + black color. I don't have any conclusive explanation on why this works but the point is that it does work.
This article at designmodo is the only one that I've found about this topic but I am still finding it difficult to explain the reason for this behavior. The one thing which we can be certain about after seeing this example is that if steps(n, start) is used, the car never comes to start position whereas if we use steps(n, end) it never reaches the end point. It is a 4 step animation but only three steps are visible, the other step happens right at the start or the end (depending on the parameter).
Solution:
.animated-play-btn {
background-color: white;
height: 50px;
width: 200px;
animation-timing-function: steps(1, end);
animation-duration: 1s;
animation-name: clipping_btn;
animation-iteration-count: infinite;
animation-fill-mode: forwards;
}
#keyframes clipping_btn {
0%, 100% {
background-color: #000;
color: white;
}
50% {
color: black;
background-color: #fff;
}
}
<button class="animated-play-btn">
coucou
</button>
The solution is to add on step and change:
animation-timing-function: steps(2, end);
by
animation-timing-function: step-end;
Here the new css:
.animated-play-btn {
background-color: white;
height: 50px;
width: 200px;
animation-timing-function: steps(1, end);
animation-duration: 1s;
animation-name: clipping_btn;
animation-iteration-count: infinite;
animation-fill-mode: forwards;
}
#keyframes clipping_btn {
from {
background-color: #000;
color: #fff;
}
50%{
color: #000;
background-color: #fff;
}
to {
background-color: #000;
color: #fff;
}
}

Resources