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 :)
Related
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
I'm working on a project where I want to have two animation with one following the other after a delay. I've gotten the two animation on the same line with one following after a delay, but I can't seem to get it work perfectly. The issue that I am having is that the first animation is starting after 0%/0vw, so it's show the animation start instead of it coming from off the page. I would really appreciate any help or advice on how to get this to work. Thank you!
.announcement {
justify-content: right;
align-items: center;
display: flex;
}
.announce {
font-size: 1.3rem;
position: relative;
/* animation: mymove 20s infinite;*/
/* animation-timing-function: linear;*/
animation: linear 15s mymove infinite;
}
.announce2 {
font-size: 1.3rem;
position: relative;
/* animation: mymove 20s infinite;*/
/* animation-timing-function: linear;*/
animation: linear 15s mymove2 infinite;
animation-delay: 5s;
}
#keyframes mymove {
from {right: 0vw;}
50% {right: 50vw !important;} /* ignored */
to {right: 100vw;}
}
#keyframes mymove2 {
from {right: 0vw;}
50% {right: 50vw !important;} /* ignored */
to {right: 100vw;}
}
<div class="announcement">
<div class="announce">
Hello
</div>
<div class="announce2">
Hello
</div>
</div>
To get the announcement off the screen to the right it needs to not only be positioned right: 0 but also to move further to the right by its own width. This can be achieved with a translation of 100%.
As an example, this snippet gives both announcements the same animation and other settings - apart from giving announement2 the animation delay.
The parent element has overflow hidden, and the body is given margin 0 to ensure that the announcements go fully from the right to the left.
body {
margin: 0;
}
.announcement {
justify-content: right;
align-items: center;
display: flex;
overflow: hidden;
}
.announce,
.announce2 {
font-size: 1.3rem;
position: relative;
animation: linear 15s mymove infinite;
right: 0;
transform: translateX(100%);
}
.announce2 {
animation-delay: 5s;
}
#keyframes mymove {
to {
right: 100vw;
transform: translateX(0%);
}
}
<div class="announcement">
<div class="announce">
Hello
</div>
<div class="announce2">
Hello
</div>
</div>
Note: if what you are wanting is an evenly spaced continuous flow then you might like to search for 'marquee' on StackOverflow - not the HTML tag which is deprecated but continuous rotating banner.
I have a little noobish CSS question If someone could share some free time to help. what I want to do is the div to stop and freeze at the position whenever I leave (hover off) my cursor, and not reset to his fixed starting position.
<script>
.rotatingDiv {
width: 50px;
height: 30px;
background-color: red;
margin: auto;
margin-top: 10rem;
cursor: pointer;
}
.rotatingDiv:hover {
animation: spin 4s linear infinite;
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</script>
<body>
<div class="rotatingDiv"> </div>
</body>
as seen on the example the div keeps reseting to the starting position which is 0deg (default) on mouse-out, so what I want to achieve is for the div to freeze at the exact degree whenever I leave my cursor (mouse out/ hover off) from the div.
I think you wanted this thing it would be work
.rotatingDiv {
width: 50px;
height: 30px;
background-color: red;
margin: auto;
margin-top: 10rem;
cursor: pointer;
animation: spin 4s linear infinite;
animation-play-state: paused;
}
.rotatingDiv:hover {
animation: spin 4s linear infinite;
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<body>
<div class="rotatingDiv"> </div>
</body>
Having an issue with an image when upon the image finishes its animation and is filled in forwards, it's opacity is lower than if i just load the image normally (with the animations taken out)
.header-container .col-2 {
display: flex;
justify-content: center;
align-items: center;
width: 50%;
z-index: -1;
}
.header-container .col-2 img {
opacity: 0; //
animation: 0.5 header ease 1.25s; // these three lines seem to be the problem
animation-fill-mode: forwards; //
}
#keyframes header {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
I have looked at the styles on my browser (chrome) and can't work out why this is happening
In the image is what the difference looks like + chrome styles
img on right has slightly lower opacity
Thanks for any suggestions / help
animation: 0.5 header ease 1.25s;
the 0.5 without the time unit is interpreted as the animation-iteration-count which, if set to 0.5 means: "Run my animation halfways."
What you want is: name, duration, easing, delay, fill-mode use:
animation: header 0.5s ease 1.25s forwards;
and use the s or ms unit for the duration value.
Here's a reminder for the Animation shorthand order:
name, duration, easing, delay, iteration-count, direction, fill-mode
.header-container .col-2 {
display: flex;
justify-content: center;
align-items: center;
width: 50%;
z-index: -1;
background: url("https://placehold.it/100x100/00f");
}
.header-container .col-2 img {
opacity: 0;
animation: header 0.5s ease 1.25s forwards;
}
#keyframes header {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<div class="header-container">
<div class="col-2">
<img src="https://placehold.it/200x200/f00" alt="Test">
</div>
</div>
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>