Run CSS3 animation only once (at page loading)
CssCss AnimationsCss Problem Overview
I'm making a simple landing page driven by CSS3. To make it look awesome there's an <a>
plopping up:
@keyframes splash {
from {
opacity: 0;
transform: scale(0, 0);
}
50% {
opacity: 1;
transform: scale(1.1, 1.1);
}
to {
transform: scale(1, 1);
}
}
And to make it even more awesome I added a hover animation:
@keyframes hover {
from {
transform: scale(1, 1);
}
to {
transform: scale(1.1, 1.1);
}
}
But there comes the problem! I assigned the animations like this:
a {
/* Some basic styling here */
animation: splash 1s normal forwards ease-in-out;
}
a:hover {
animation: hover 1s infinite alternate ease-in-out;
}
Everything works just fine: The <a>
splashes into the users face and has a nice vibration when he hovers it. Bit as soon as the user blurs the <a>
the smooth stuff ends abruptly and the <a>
repeats the splash
-animation. (Which is logical to me, but I don't want it to)
Is there some way to solve this problem without some JavaScript Class Jiggery Pokery?
Css Solutions
Solution 1 - Css
After hours of googling: No, it's not possible without JavaScript. The animation-iteration-count: 1;
is internally saved in the animation
shothand attribute, which gets resetted and overwritten on :hover
. When we blur the <a>
and release the :hover
the old class reapplies and therefore again resets the animation
attribute.
There sadly is no way to save a certain attribute states across element states.
You'll have to use JavaScript.
Solution 2 - Css
If I understand correctly that you want to play the animation on A
only once youu have to add
animation-iteration-count: 1
to the style for the a
.
Solution 3 - Css
It can be done with a little bit of extra overhead.
Simply wrap your link in a div, and separate the animation.
the html ..
<div class="animateOnce">
<a class="animateOnHover">me!</a>
</div>
.. and the css ..
.animateOnce {
animation: splash 1s normal forwards ease-in-out;
}
.animateOnHover:hover {
animation: hover 1s infinite alternate ease-in-out;
}
Solution 4 - Css
I just got this working on Firefox and Chrome. You just add/remove the below class accordingly to your needs.
.animateOnce {
-webkit-animation: NAME-OF-YOUR-ANIMATION 0.5s normal forwards;
-moz-animation: NAME-OF-YOUR-ANIMATION 0.5s normal forwards;
-o-animation: NAME-OF-YOUR-ANIMATION 0.5s normal forwards;
}
Solution 5 - Css
An easy solution to solve this problem is by just adding more seconds to the animation in a:hover
and taking advantage of the transitions in @keyframes
a:hover {
animation: hover 200s infinite alternate ease-in-out;
}
Just make the progression of @keyframes
go faster by using percentages.
@keyframes hover {
0% {
transform: scale(1, 1);
}
1% {
transform: scale(1.1, 1.1);
}
100% {
transform: scale(1.1, 1.1);
}
}
200 seconds or 300 seconds in the animation is more than enough to make sure the animation doesn't restart. A normal person won't last more than a few seconds hovering an image.
Solution 6 - Css
Just use
animation: hover 1s ease-in-out forwards;
Solution 7 - Css
Impossible in CSS only, you need a javascript workaround. As already explained by some here, the animation-iteration-count
property is reset on a :hover. The best is to do everything in javascript, but for reasons of ease of customization of the code you may want to keep the possibility of doing something in CSS.
So, in JS :
// adding a class to the html tag, during the animation time
const startPage = (() => {
const html = document.documentElement,
s = 'start-map'
html.classList.add(s)
window.addEventListener('load', function() {
setTimeout(() => {
html.classList.remove(s)
}, 1500) // the time must be at least equal to the duration of the CSS animation (personally I put a little more).
})
})()
And for the CSS:
/* the presence of the `.start` class conditions the animation */
.start .leaflet-marker-pane {
animation: animDrop 1s ease;
}
Solution 8 - Css
The following code without "iteration-count: 1"
was resulting in all line items pulsing after entering, until the last item loaded, even though 'pulse was not being used.
<li class="animated slideInLeft delay-1s animation-iteration-count: 1"><i class="fa fa-credit-card" aria-hidden="true"></i> 1111</li>
<li class="animated slideInRight delay-1-5s animation-iteration-count: 1"><i class="fa fa-university" aria-hidden="true"></i> 222222</li>
<li class="animated lightSpeedIn delay-2s animation-iteration-count: 1"><i class="fa fa-industry" aria-hidden="true"></i> aaaaaa</li>
<li class="animated slideInLeft delay-2-5s animation-iteration-count: 1"><i class="fa fa-key" aria-hidden="true"></i> bbbbb</li>
<li class="animated slideInRight delay-3s animation-iteration-count: 1"><i class="fa fa-thumbs-up" aria-hidden="true"></i> ccccc</li>
Solution 9 - Css
So i just found a solution for that: In the hover animation do this:
animation: hover 1s infinite alternate ease-in-out,splash 1;