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);
}
}
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;
}
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>
As i understand, when i change the animation-direction from normal to reverse during a specific animation, the element will move towards the opposite direction right away starting from where it is now.But it seems i am wrong , here is the http://codepen.io/johnwaynerui/pen/bZvRLm When i click the reverse button, the circle does not turn around right away and moving towards the opposite direction. Are there something i misunderstand?
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"> </script>
<div id="circle"></div>
<button id='reverse'>reverse</button>
#keyframes move-right {
0% {
transform: translateX(0px);
}
20% {
transform: translateX(200px);
}
40% {
transform: translateX(400px);
}
60% {
transform: translateX(600px);
}
80% {
transform: translateX(800px);
}
100% {
transform: translateX(1000px);
}
}
#circle {
height: 50px;
width: 50px;
border-radius:25px;
background-color: teal;
-webkit-animation-duration: 20s;
-webkit-animation-timing-function: linear;
-webkit-animation-name: move-right;
-webkit-animation-iteration-count: infinite;
animation-fill-mode: both;
position:absolute;
left:30%;
top:20%;
}
#circle.reverse {
animation-direction: reverse;
}
$('#reverse').click(function () {
$('#circle').toggleClass('reverse');
});
You can check the documentation for animation-direction here.
It clearly states that, for a reverse value:
The animation plays backward each cycle. Each time the animation cycles, the animation resets to the end state and starts over again.
As per my understanding, the moment you add animation-direction: reverse; to your animation, it goes in reverse direction mode that means the end-point of original animation becomes its start-point and vice-versa. So, if your animation has run first 20% and you change its animation-direction to reverse its start and end-points get interchanged, and it suddenly jumps to the 20% point relative to these changed end-points. That's why you notice that your circle suddenly jumps to far right and then continues its movement towards left.
$('#reverse').click(function () {
$('#circle').toggleClass('reverse');
});
#keyframes move-right {
0% {
transform: translateX(0px);
}
20% {
transform: translateX(200px);
}
40% {
transform: translateX(400px);
}
60% {
transform: translateX(600px);
}
80% {
transform: translateX(800px);
}
100% {
transform: translateX(1000px);
}
}
#circle {
height: 50px;
width: 50px;
border-radius:25px;
background-color: teal;
-webkit-animation-duration: 20s;
-webkit-animation-timing-function: linear;
-webkit-animation-name: move-right;
-webkit-animation-iteration-count: infinite;
animation-fill-mode: both;
position:absolute;
left:30%;
top:20%;
}
#circle.reverse {
animation-direction: reverse;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"> </script>
<div id="circle"></div>
<button id='reverse'>reverse</button>
Please tell me how to make a "smooth" animations.
I have the keyframes, which describes the behavior of the animation in the download. And at Hover, connects the other keyframes (animation and changes its course).
Between them the change occurs sharpness.
Here is an example of field http://jsfiddle.net/g4wvqrL8/
.icon-1 {
width: 3em;
height: 3em;
margin: 85px auto;
animation: pull 3s infinite reverse ease-in-out
}
.icons {
width:80%;
margin: 0 auto;
height:90px;
}
.icons:hover {
animation: rotate360 4s infinite reverse cubic-bezier(0.4, 0, 1, 1);
}
#keyframes pull {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-55px);
}
100%{
transform: translateY(0px);
}
}
#keyframes rotate360 {
0% {
transform: rotate(0deg) translateX(30px);
}
100% {
transform: rotate(360deg) translateX(30px);
}
}
Question: how at different keyframes at Hover to make the smooth transition of 2 types of animation?
I tried to make transition (shifts them to the desired trajectory at Hover and start a new animation, but smooth still was not).
Or how to start the animation with a place to stay until this animation ??
Prompt, all thanks in advance!
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.