Trigger CSS Animations in JavaScript
Asked Answered
P

10

66

I don't know how to use JQuery, so I need a method which could trigger an animation using JavaScript only.

I need to call/trigger CSS Animation when the user scrolls the page.

function start() {
  document.getElementById('logo').style.animation = "anim 2s 2s forward";
  document.getElementById('earthlogo').style.animation = "anim2 2s 2s forward";
}
* {
  margin: 0px;
}

#logo {
  position: fixed;
  top: 200px;
  height: 200px;
  width: 1000px;
  left: 5%;
  z-index: 4;
  opacity: 0.8;
}

#earthlogo {
  position: fixed;
  top: 200px;
  height: 120px;
  align-self: center;
  left: 5%;
  margin-left: 870px;
  margin-top: 60px;
  z-index: 4;
  opacity: 0.9;
}

@keyframes anim {
  50% {
    filter: blur(10px);
    transform: rotate(-15deg);
    box-shadow: 0px 0px 10px 3px;
  }
  100% {
    height: 100px;
    width: 500px;
    left: 10px;
    top: 10px;
    box-shadow: 0px 0px 15px 5px rgba(0, 0, 0, 0.7);
    background-color: rgba(0, 0, 1, 0.3);
    opacity: 0.7;
  }
}

@keyframes anim2 {
  50% {
    filter: blur(40px);
    transform: rotate(-15deg);
  }
  100% {
    height: 60px;
    width: 60px;
    left: 10px;
    top: 10px;
    margin-left: 435px;
    margin-top: 30px;
    opacity: 0.8;
  }
}

#backstar {
  position: fixed;
  width: 100%;
  z-index: 1;
}

#earth {
  position: absolute;
  width: 100%;
  z-index: 2;
  top: 300px;
}
<img src="logo.png" id="logo" onclick="start();">
<img src="earthlogo.gif" id="earthlogo" onscroll="start();">
<img src="earth.png" id="earth">
<img src="stars.jpg" id="backstar">
Puberulent answered 30/6, 2017 at 12:34 Comment(2)
onscroll on an image makes no sense.Vignette
Search how to intercept a scroll even of the page with jquery and how to add a class. Pretty basic question mate do some research.Roil
C
44

The simplest method to trigger CSS animations is by adding or removing a class - how to do this with pure Javascript you can read here:

How do I add a class to a given element?

If you DO use jQuery (which should really be easy to learn in basic usage) you do it simply with addClass / removeClass.

All you have to do then is set a transition to a given element like this:

.el {
    width:10px;
    transition: all 2s;
}

And then change its state if the element has a class:

.el.addedclass {
    width:20px;
}

Note: This example was with transition. But for animations its the same: Just add the animation on the element which has a class on it.

There is a similar question here: Trigger a CSS keyframe animation via scroll

Completion answered 30/6, 2017 at 12:44 Comment(1)
el.classList.add('myClass') or classList.remove() has replaced addClass / removeClass see developer.mozilla.org/en-US/docs/Web/API/Element/classListMorris
B
41

This is how you can use vanilla JavaScript to change/trigger an animation associated with an HTML element.

First, you define your animations in CSS.

@keyframes spin1 { 100% { transform:rotate(360deg); } }
@keyframes spin2 { 100% { transform:rotate(-360deg); } }
@keyframes idle { 100% {} }

Then you use javascript to switch between animations.

document.getElementById('yourElement').style.animation="spin2 4s linear infinite";

Note: 'yourElement' is the target HTML element that you wish to animate.

For example: <div id="yourElement"> ... </div>

Bodrogi answered 27/5, 2020 at 16:31 Comment(1)
You can use an element event-attribute to fire the with this. For example: <div onload="this.style.animation='spin2 4s linear infinite'"> ... </div>Warfare
H
25

Adding and removing the animation class does not work in a function. The delay is simply too little. As suggested by this article you can request the browser to reflow and then add the class. The delay isn't an issue in that case. Hence, you can use this code:

element.classList.remove("animation")
element.offsetWidth
element.classList.add("animation")

The best thing is, this works everywhere. All credit goes to the article.

Hussein answered 24/8, 2020 at 13:6 Comment(1)
The scary thing is that this solution relying on side effects of a computed getter property is the least hacky one here...Dreamworld
S
20

A more idiomatic solution is to use the Web Animations API.

Here is the example from MDN:

document.getElementById("alice").animate(
  [
    { transform: 'rotate(0) translate3D(-50%, -50%, 0)', color: '#000' },
    { color: '#431236', offset: 0.3 },
    { transform: 'rotate(360deg) translate3D(-50%, -50%, 0)', color: '#000' }
  ], {
    duration: 3000,
    iterations: Infinity
  }
);

OP's example:

document.getElementById('logo').animate(
    [
        {},
        {
            filter: 'blur(10px)',
            transform: 'rotate(-15deg)',
            box-shadow: '0px 0px 10px 3px',
        },
        {
            height: '100px',
            width: '500px',
            left: '10px',
            top: '10px',
            box-shadow: '0px 0px 15px 5px rgba(0, 0, 0, 0.7)',
            background-color: 'rgba(0, 0, 1, 0.3)',
            opacity: '0.7',
        },
    ],
    {
        duration: 2000,
        delay: 2000,
        fill: 'forwards',
    },
)

At the time of writing, it's supported in all major browsers except IE. Supported browsers

Seminal answered 13/2, 2022 at 4:50 Comment(2)
I wonder if it's possible to refer to a css animation @keyframes definition by it's name instead of inlining style values in js...Dreamworld
@Dreamworld Maybe this is what you need? danielcwilson.com/blog/2020/04/css-in-the-waapi I haven't tried it myself, but if I'm reading it correctly, it could help you reference a CSS @keyframes from JSSeminal
C
6

I have a similar problem. The best answer didn’t work for me, but when I added the delay it worked. The following is my solution.

CSS

.circle_ani1,
.circle_ani2 {
    animation-duration: 1s;
    animation-iteration-count: 1;
}

.circle_ani1 {
    animation-name: circle1;
}

.circle_ani2 {
    animation-name: circle2;
}

JS

let temp_circle1 = $('.TimeCountdown_circle1').removeClass('circle_ani1');
let temp_circle2 = $('.TimeCountdown_circle2').removeClass('circle_ani2');
window.setTimeout(function() {
    temp_circle1.addClass('circle_ani1');
    temp_circle2.addClass('circle_ani2');
}, 50);
Chromogen answered 19/8, 2020 at 6:8 Comment(0)
S
5

Vanilla JS version

document.getElementById('logo').classList.add("anim");
document.getElementById('earthlogo').classList.add("anim2");
Saiga answered 30/6, 2017 at 12:41 Comment(1)
This may be a correct answer, but some detail as to what is different or an explanation of the solution would server the OP as well as future SO users looking for answers that teach them something also.Von
F
4

You could use animation-play-state (Mdn docs) like this

element.style.animationPlayState = "paused/running"

Code snippet:

function play() {
  document.getElementById("div").style.animationPlayState = "running";
}

function pause() {
  document.getElementById("div").style.animationPlayState = "paused";
}
.animation {
  width: 50px;
  height: 50px;
  background-color: red;
  position: relative;
  animation-name: example;
  animation-duration: 2s;
  animation-play-state: paused;
  animation-iteration-count: infinite;
}

@keyframes example {
  0% {
    background-color: red;
    left: 0px;
    top: 0px;
  }
  25% {
    background-color: yellow;
    left: 50px;
    top: 0px;
  }
  50% {
    background-color: blue;
    left: 50px;
    top: 50px;
  }
  75% {
    background-color: green;
    left: 0px;
    top: 50px;
  }
  100% {
    background-color: red;
    left: 0px;
    top: 0px;
  }
}
<button onclick="play()">Play</button>
<button onclick="pause()">Pause</button><br><br>
<div id="div" class="animation"></div>
Flannery answered 4/7, 2022 at 23:2 Comment(0)
M
3

You could use CSS to hide the image / animation and show when the user scrolls. This would work like this:

CSS:

div {
    border: 1px solid black;
    width: 200px;
    height: 100px;
    overflow: scroll;
}

#demo{
    display: none;
}

HTML:

<div id="myDIV"> </div>

<div id="demo">
     <img src="earthlogo.gif" id="earthlogo" alt="Thanks for scrolling. Now you see me">
</div>

Your javascript just needs to include an eventListener to call the function which triggers the display of your animation.

JS:

document.getElementById("myDIV").addEventListener("scroll", start);

function start() {
    document.getElementById('demo').style.display='block';
}
Mooch answered 30/6, 2017 at 13:0 Comment(1)
I use this trick nearly everytimeCalvary
H
1

Here's the main code:

HTML:

<img id="myImg">

CSS:

#myImg {
    //properties
    animation: animate 2s linear infinite //infinite is important!
}
@keyframes animate {
    //animation base
}

JS:

document.getElementById("myImg").style.webkitAnimationPlayState = "paused";
window.addEventListener("scroll", function() {
    document.getElementById("myImg").style.webkitAnimationPlayState = "running";
    setTimeout(function() {
        document.getElementById("myImg").style.webkitAnimationPlayState = "paused";
    }, 2000);
});
Hendiadys answered 29/1, 2020 at 13:27 Comment(0)
N
1

If you want Animations i recommend you create a CSS class which you toggle on a Condition whit JS: CSS

.animation {
 animation: anim 2s ease infinite;
 transition: .2s
}

JS

// Select your Element

$element.document.querySelector(".yourElement");
$element.addEventListner('click', () => {
 $element.classList.toggle("animation")
})
Novick answered 29/1, 2020 at 13:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.