I have an animation that has an infinite iterations count:
.spinner {
animation: spinnerAnimation 2s linear infinite;
}
What I want is to make the animation finish the current animation cycle and stop it on a button click (not really on a button click, but this is to make things easier to understand):
$("button").click(function() {
$(".spinner").addClass("stop");
})
This will add a stop class to the spinner:
.spinner.stop {
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
}
It doesn't work really smooth, but I don't care about smoothness much in this case:
http://codepen.io/Deka87/pen/OXZvdm
The only problem is that this won't stop the animation in IE edge, i.e. things don't work in IE (versions that support animations). Any ideas?
PS: animation-play-state: pause; is not what I need, because this won't make the animation finish the current animation cycle, but pause it in its current position instead.
PSS: I am really looking for a CSS only solution, i.e. make it work inside .spinner.stop{}.
You had a problem with the name of your keyframe name - spinnerAnimation vs preloaderAnimation
The only way I was able to set IE to stop the animation was to set animation: none; inside the .stop class:
$("button").click(function() {
$(".spinner").addClass("stop");
})
.spinner {
width: 30px; height: 30px;
background: green;
animation: spinnerAnimation 2s linear infinite;
}
.spinner.stop {
-webkit-animation-iteration-count: 1;
animation: none;
}
button {
margin-top: 20px;
}
#-webkit-keyframes spinnerAnimation {
0% {
-webkit-transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes spinnerAnimation {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="spinner"></div>
<button>Stop spinner</button>
Related
I'm using CSS keyframes to rotate an element on its hover state.
How do I make the element finish its animation even the mouse leave the element before it actually end?
For example, if I move my mouse out of the element(stop hovering) while the element only rotating to 180 degree (the full animation is 360 degree), it immediately stop the animation and go back to its original state instead of finish the animation.
#rotate {
width: 120px;
height: 120px;
background-color: orange;
}
#rotate:hover {
animation: rotating 1s ease 0s 1 normal forwards;
}
#keyframes rotating {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
<div id="rotate"></div>
You need to use Javascript for this, the following snippet is shown using some jQuery, a working example:
$("#rotate").on({
mouseenter() {
$(this).addClass("animated");
},
animationend() {
$(this).removeClass("animated");
},
});
#rotate {
width: 120px;
height: 120px;
background-color: orange;
}
.animated {
animation: rotating 1s ease 0s 1 normal forwards;
}
#keyframes rotating {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="rotate"></div>
Make sure that the class animated is with the animation, and #rotate is the box you want to spin.
This worked for my situation as it pauses and starts from where it left off. For simple rotation, this feels nicer than the jump you usually get from hovering in and out.
#keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.name-star {
right: 5px;
top: 15px;
animation: 5s rotate infinite;
animation-play-state: paused;
animation-timing-function: ease-in;
}
.mat-grid-tile:hover .name-star {
animation-play-state: running;
}
Current I am using some animations with my sliding ionic list such as sliding in from left to right and content from fading in as per this tutorial. https://www.joshmorony.com/how-to-create-animations-with-css-in-ionic/
#-webkit-keyframes animateInPrimary {
0% {
-webkit-transform: translate3d(-100%,0,0);
}
100% {
-webkit-transform: translate3d(0,0,0);
}
}
#-webkit-keyframes animateInSecondary{
0% {
opacity: 0;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.animate-in-primary {
-webkit-animation: animateInPrimary;
animation: animateInPrimary;
-webkit-animation-duration: 750ms;
animation-duraton: 750ms;
}
.animate-in-secondary {
-webkit-animation: animateInSecondary ease-in 1;
animation: animateInSecondary ease-in 1;
-webkit-animation-duration: 750ms;
animation-duraton: 750ms;
}
Now I would want the ion-items to slide one after the other. I think I have to use the css property -webkit-animation-delay. But i am not sure where to insert it. Hope someone can help. Thanks,
Ashley
If you wanted to do this with CSS animations then what you would need to do is add an incremental class to each list item and then stagger your animations accordingly as demonstrated here: CSS Animations with delay for each child element
The easier way to do this is with the built in stagger function of the animations module - take a look at this article: https://coursetro.com/posts/code/78/Creating-Stagger-Animations-in-Angular-4#
I have an element which functions as a tri-state checkbox. I want to run an animation on that element whenever the state changes. Essentially, the element starts with no classes attached to indicate the first state. Then I add a class for one state, then remove that class and add a different one for the second state.
It works on the first click but the animation doesn't play on subsequent clicks. Here's what I have so far:
$('button').click(function() {
var $div = $('div');
if (!$div.hasClass('is-colored')) {
$div.addClass('green is-colored');
} else {
$div.toggleClass('green red');
}
});
#keyframes Animation {
from {
opacity: 0;
transform: scaleX(0) scaleY(0);
}
to {
opacity: 1;
transform: scaleX(1) scaleY(1);
}
}
.green {
background-color: #0F0;
-webkit-animation: Animation 0.25s linear forwards;
-moz-animation: Animation 0.25s linear forwards;
animation: Animation 0.25s linear forwards;
}
.red {
background-color: #F00;
/* I tried applying the animation on the second state but this isn't working */
-webkit-animation: Animation 0.25s linear forwards;
-moz-animation: Animation 0.25s linear forwards;
animation: Animation 0.25s linear forwards;
}
div {
width: 100px;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<button>Change Color</button>
I know it's possible to restart an animation with JavaScript and as of 3 years ago it didn't seem to be possible to do this without JavaScript.
In short, is it possible to perform the same animation on the same element multiple times using only CSS and toggling classes (i.e, no timeout required)?
What's happening is because the state never gets a reset so the animation doesn't kick in again. What you want to do is remove the color class as it resets, "wait" (0 seconds) then have the new class kick in for the animation.
The change is like this for green, see below for full changes:
$div.removeClass('green');
setTimeout(function() {
$div.addClass('red');
}, 0);
Edit: To do this without javascript delay. The only way is to create another version of the animation so it constantly runs a different animation:
$('button').click(function() {
var $div = $('div');
if (!$div.hasClass('is-colored')) {
$div.addClass('green is-colored');
} else {
$div.toggleClass('green red');
}
});
#keyframes Animation {
from {
opacity: 0;
transform: scaleX(0) scaleY(0);
}
to {
opacity: 1;
transform: scaleX(1) scaleY(1);
}
}
#keyframes Animation2 {
from {
opacity: 0;
transform: scaleX(0) scaleY(0);
}
to {
opacity: 1;
transform: scaleX(1) scaleY(1);
}
}
.green {
background-color: #0F0;
-webkit-animation: Animation 0.25s linear forwards;
-moz-animation: Animation 0.25s linear forwards;
animation: Animation 0.25s linear forwards;
}
.red {
background-color: #F00;
/* I tried applying the animation on the second state but this isn't working */
-webkit-animation: Animation2 0.25s linear forwards;
-moz-animation: Animation2 0.25s linear forwards;
animation: Animation2 0.25s linear forwards;
}
div {
width: 100px;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<button>Change Color</button>
I'm coding a CSS3 effect fired on mouseover; this effect simply animate an inner div scaling it endlessly.
All works great, but when I move the mouse away the div suddenly return to its original size. I would like to add a smooth effect to scale the div back.
I already checked the suggestion of this post:
Make CSS Hover state remain after "unhovering"
Unfortunately the code posted doesn't work :(
In my opinion my issue could be related with the "infinite" loop of the scale effect.
THe goal I would like to gain is the on mouse-out the image could return to its original size smoothly.
Here's the code: https://jsfiddle.net/9dtqpsLa/1/
CSS
#keyframes imageZoom{
0% { transform: scale(1); }
50% { transform: scale(1.24); }
100% { transform: scale(1);}
}
#-moz-keyframes imageZoom{
0% { -moz-transform: scale(1);}
50% { -moz-transform: scale(1.24); }
100% { -moz-transform: scale(1); }
}
#-webkit-keyframes imageZoom{
0% { -webkit-transform: scale(1); }
50% {-webkit-transform: scale(1.24); }
100% { -webkit-transform: scale(1); }
}
#-ms-keyframes imageZoom{
0% { -ms-transform: scale(1); }
50% { -ms-transform: scale(1.24); }
100% { -ms-transform: scale(1); }
}
.article:hover .imageWrapper {
animation: imageZoom linear 10s;
animation-iteration-count: infinite;
-webkit-animation: imageZoom linear 10s;
-webkit-animation-iteration-count: infinite;
-moz-animation: imageZoom linear 10s;
-moz-animation-iteration-count: infinite;
-ms-animation: imageZoom linear 10s;
-ms-animation-iteration-count: infinite;
transform-origin: 50% 80%;
}
.article {
background-color: #e6e6e6;
overflow: hidden;
width: 300px;
height: 300px;
}
.imageWrapper {
background-image: url('http://www.astutegraphics.com/images/blog/tutorials/widthscribe_patterns_18_mar_2013/floral-seamless-pattern.png');
width: 300px;
height: 300px;
}
HTML
<div class="article">
<div class="imageWrapper">
</div>
</div>
Please, could you help me?
Thanks so much
GOALS:
1. Have the image animate expansion and contraction on hover
2. Have the image animate to original state on mouseleave
PROBLEMS:
With CSS, I don't know how to use both an animation and a transition. The animation is the pulsing on hover. The transition is the return to default animation. The only way I could envision doing it is with JS. See each section for notes
https://jsfiddle.net/Bushwazi/9dtqpsLa/5/
HTML:
notes: same as example provided
<div class="article">
<div class="imageWrapper"></div>
</div>
CSS:
notes:
1. animation removed.
2. The scale is only fired with the existence of [data-dir='expand'].
3. transform-origin and transition moved into the default state of .imageWrapper
4. need to add prefixes
.article[data-dir='expand'] .imageWrapper {
transform:scale(1.24)
}
.article {
background-color: #e6e6e6;
overflow: hidden;
width: 300px;
height: 300px;
}
.imageWrapper {
background-image: url('http://www.astutegraphics.com/images/blog/tutorials/widthscribe_patterns_18_mar_2013/floral-seamless-pattern.png');
width: 300px;
height: 300px;
transform-origin: 50% 80%;
transition:all 10.0s linear 0.0s;
}
JAVASCRIPT:
notes:
1. all new
/*
1. on hover aka 'mouseenter' start the animation
2. 10 seconds in, change direction of the animation based on the `isHovering` variable
3. on exit aka 'mouseleave', return to default
*/
var thisArticle = document.querySelector('.article'),
thisTimer = '',
isHovering = false;
thisArticle.addEventListener('mouseenter', function(){
console.log('mouseenter');
thisArticle.setAttribute('data-dir', 'expand');
thisTimer = setInterval(fireAnimation, 10000);
isHovering = true
}, false);
thisArticle.addEventListener('mouseleave', function(){
console.log('mouseleave');
thisArticle.removeAttribute('data-dir');
isHovering = false;
clearInterval(thisTimer);
}, false);
var fireAnimation = function(){
if(isHovering){
if(thisArticle.getAttribute('data-dir') === 'expand'){
thisArticle.removeAttribute('data-dir');
} else {
thisArticle.setAttribute('data-dir', 'expand');
}
} else {
clearInterval(thisTimer);
}
alert('change direction');
}
MORE IDEAS
1. I used a data attribute, but I would prefer to use classList. Wasn't sure how to incorporate that into the fiddle in 30 seconds, so skipped it.
2. The return to default animation has no awareness of the scale when you leave, so it takes 10 seconds no matter what. I'm sure there is a way to make this better.
Once you the mouse is moved away from the element, the styles in the :hover pseudo class gets removed from your element, effectively putting it back where it started.
What you want to do is start and pause the animation:
Here is your fiddle, I edited it a bit and exploded the short-hand and removed -webkit, -ms, etc:
https://jsfiddle.net/9dtqpsLa/4/
#keyframes imageZoom {
100% {
transform: scale(4);
}
}
.article:hover .imageWrapper {
animation-play-state: running;
}
.article {
background-color: #e6e6e6;
overflow: hidden;
width: 300px;
height: 300px;
}
.imageWrapper {
background-image: url('http://www.astutegraphics.com/images/blog/tutorials/widthscribe_patterns_18_mar_2013/floral-seamless-pattern.png');
width: 300px;
height: 300px;
transform-origin: 50% 80%;
animation-name: imageZoom;
animation-duration: 2s;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: both;
animation-timing-function: ease-in;
animation-fill-mode: forwards;
animation-play-state: paused;
}
Notice that all the animation logic has moved to the base class, and the :hover only kicks off the animation.
I'm entering the world of CSS3 animations and transitions so please forgive my ignorance.
Here's the simplified version of what I'm trying to do:
I have a ball that "pulsates" infinitely via CSS3 keyframes
I want the ball to grow bigger and stay like that when I hover over it
I want the ball to become small again when I move the mouse away from it and keep pulsating (all the transitions need to be smooth, of course).
Here's my stab at it using a mix of CSS3 animations and transitions (testing this on Chrome so far, hence webkit prefixes):
#-webkit-keyframes pulsate {
from {
-webkit-transform: scale(0.7);
}
to {
-webkit-transform: scale(0.8);
}
}
.ball {
background: blue;
width: 100px;
height: 100px;
border-radius: 50%;
transition: all 1s;
-webkit-transform: scale(0.7);
-webkit-transform-origin: center center;
-webkit-animation-duration: 800ms;
-webkit-animation-name: pulsate;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: ease-in-out;
}
.ball:hover {
-webkit-transform: scale(2);
-webkit-animation-play-state: paused; /* transition works but gets reset at the end*/
/*-webkit-animation: 0;*/ /* transition works only one time, and no smooth transition on mouse out */
}
jsFiddle Demo
The result is pretty close but as soon as the ball finishes expanding on hover, it suddenly becomes small again (don't understand why). I also tried disabling the animation via -webkit-animation: 0; instead of pausing it but it doesn't work well either.
I tried a different approach that uses keyframes only (no transitions) by attempting to call a different keyframe set on hover:
#-webkit-keyframes pulsate {
from {
-webkit-transform: scale(0.7);
}
to {
-webkit-transform: scale(0.8);
}
}
#-webkit-keyframes expand {
to {
-webkit-transform: scale(2);
}
}
#-webkit-keyframes shrink {
to {
-webkit-transform: scale(0.7);
}
}
.ball {
background: blue;
width: 100px;
height: 100px;
border-radius: 50%;
transition: all 2s;
-webkit-transform: scale(0.7);
-webkit-transform-origin: center center;
-webkit-animation-duration: 800ms, 800ms;
-webkit-animation-name: shrink, pulsate;
-webkit-animation-iteration-count: 1, infinite;
-webkit-animation-direction: normal, alternate;
-webkit-animation-timing-function: ease-in-out, ease-in-out;
}
.ball:hover {
-webkit-animation-name: expand;
-webkit-animation-iteration-count: 1;
-webkit-animation-direction: normal;
-webkit-animation-fill-mode: forwards;
}
jsFiddle Demo
The ball stays big as long as the mouse is over it but there's still no smooth transition when the mouse moves away from the ball. I expect it to play the shrink animation instead but it doesn't.
Am I missing something or this is impossible to implement with just pure CSS at the moment?
// Related thread but didn't work for me: Stop animation and start transition on hover
You need to add an animation delay to allow the transition to complete because it reverts back to scale(.7) at the start of the animation. Updated jsFiddle
-webkit-animation-delay:1s;
EDIT
I realized that the answer I posted here was not fully correct. True, the delay animated the transition from big back to small, but if you hover over the pulsing ball when its expanded it jumps back to it's 0 value of .7 before animating to the large scale.
Updated Demo
I came up with a fix that just uses some javascript to fix it based on this article. You do have to change the CSS a little, but it's not very noticeable in the outcome. Here is the updated code
/* CSS */
body {margin: 100px;}
#-webkit-keyframes pulsate {
0% {
-webkit-transform: scale(0.7);
}
50% {
-webkit-transform: scale(0.8);
}
100% {
-webkit-transform: scale(0.7);
}
}
.ball {
background: blue;
width: 100px;
height: 100px;
border-radius: 50%;
-webkit-transform: scale(0.7);
-webkit-transform-origin: center center;
transition: all 1s;
}
.ball.animated {
-webkit-animation-duration: 1600ms;
-webkit-animation-name: pulsate;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: ease-in-out;
}
/* Javascript */
var ball = document.getElementsByClassName('ball')[0],
pfx = ["webkit", "moz", "MS", "o", ""],
hovered = false;
function AnimationListener() {
if(hovered)
{
ball.classList.remove('animated');
ball.style.webkitTransform = 'scale(2)';
ball.style.transform = 'scale(2)';
}
}
function TransitionListener() {
if(!hovered)
{
ball.classList.add('animated');
}
}
function PrefixedEvent(element, type, callback) {
for (var p = 0; p < pfx.length; p++) {
if (!pfx[p]) type = type.toLowerCase();
element.addEventListener(pfx[p]+type, callback, false);
}
}
PrefixedEvent(ball, "AnimationIteration", AnimationListener);
ball.onmouseover = function() {
hovered = true;
}
ball.onmouseout = function() {
hovered = false;
PrefixedEvent(ball, "TransitionEnd", TransitionListener);
ball.style.webkitTransform = 'scale(.7)';
ball.style.transform = 'scale(.7)';
}
Just update this CSS rule, I have added From & To - in Expand & Shrink:
#-webkit-keyframes expand {
from {
-webkit-transform: scale(1);
}
to {
-webkit-transform: scale(2);
}
}
#-webkit-keyframes shrink {
from {
-webkit-transform: scale(2);
}
to {
-webkit-transform: scale(1);
}
}