95

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?

9 Answers 9

59

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Try adding :not(:hover) to the selector of the splash animation.
@silvinci can you give Javascript code that solved this issue?
@Dchris Just add a a class like "animate-this" and remove it after the animation finished.
@buschtoens How did you manage to know when the animation has finished with JS?
@buschtoens I'm sure you meant to provide more information but found yourself unable at the time. When you can, please provide more context as to why your answer could not be solved the way you wanted.
|
49

If I understand correctly that you want to play the animation on A only once you have to add

animation-iteration-count: 1

to the style for the a.

1 Comment

Yup. Works in Chrome since v43, and most current browsers: developer.mozilla.org/en-US/docs/Web/CSS/…
32

It can be done with a little bit of extra overhead.

Simply wrap your link in a div, and separate the animation.

.animateOnce {
  animation: splash 1s normal forwards ease-in-out;
}

.animateOnHover:hover {
  animation: hover 1s infinite alternate ease-in-out;
}
@keyframes splash {
    from {
        opacity: 0;
        transform: scale(0, 0);
    }
    50% {
        opacity: 1;
        transform: scale(1.1, 1.1);
    }
    to {
        transform: scale(1, 1);
    }
}

@keyframes hover {
    from {
        transform: scale(1, 1);
    }
    to {
        transform: scale(1.1, 1.1);
    }
}
<div class="animateOnce">
  <a class="animateOnHover">me!</a>
</div>

1 Comment

Nice idea. But in the end I shall prefere JS extra code over HTML overhead. Still +1 ;)
22

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;
}

Comments

11

Just use

animation: hover 1s ease-in-out forwards;

1 Comment

While this code snippet may solve the problem, it doesn't explain why or how it answers the question. Please include an explanation for your code, as that really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
1

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.

Comments

0

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'
  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;
}

Comments

-1

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>

Comments

-1

So i just found a solution for that: In the hover animation do this:

animation: hover 1s infinite alternate ease-in-out,splash 1;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.