This question already has answers here:
Restart animation in CSS3: any better way than removing the element?
(14 answers)
Closed 1 year ago.
I am trying to get an animation to run whenever a button is clicked. Right now, it only runs if the page is refreshed and does not run again on repeated clicks of the button.
function myPlayFunction(el){ document.getElementById("myTest").style.animationPlayState = "running";
}
#myTest {
width: 100px;
height: 100px;
background: red;
position: relative;
animation-name: example;
animation-duration: 3s;
animation-delay: 1s;
animation-play-state: paused;
}
#keyframes example {
0% {background-color: yellow;}
50% {background: purple;}
100%{background: red;}
}
<div id="myTest"></div>
<div><button onclick="myPlayFunction(this)" class="fas fa-play"> Click this</button></div>
As you can see in my example i detect with addEventListener the finish of animation then reset animation
const myTest = document.getElementById("myTest");
function myPlayFunction(el) {
myTest.style.animationPlayState = "running";
}
myTest.addEventListener("animationend", () =>{
myTest.style.animation = 'none';
myTest.offsetHeight;
myTest.style.animation = null;
}, false);
#myTest {
width: 100px;
height: 100px;
background: red;
position: relative;
animation-name: example;
animation-duration: 3s;
animation-delay: 1s;
animation-play-state: paused;
}
#keyframes example {
0% {
background-color: yellow;
}
50% {
background: purple;
}
100% {
background: red;
}
}
<div id="myTest"></div>
<div>
<button onclick="myPlayFunction(this)" class="fas fa-play"> Click this</button>
</div>
I'm a bit confused about how to trigger multiple animations for an element using javascript.
I'm trying to get an element (.hud) to fade-in and also bounce when clicked. Currently it will only do one or the other. The second animation class is being added to the element in a on click event. The class gets added but the animation does not play. How would I construct my code for the animation to fade-in and also bounce on click?
<!DOCTYPE html>
<html>
<head>
<style>
.anim {
animation-name: bounceIn_1;
animation-duration: .5s;
}
.hud {
width: 100px;
height: 100px;
background-color: red;
animation-name: fade-in;
animation-duration: .5s;
}
#-webkit-keyframes fade-in {
0% {
opacity: 0; }
100% {
opacity: 1; } }
#-webkit-keyframes bounceIn_1{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scaleX(1);transform:scaleX(1)}}
</style>
</head>
<body>
<p>This box should fade in and bounce on click</p>
<div class="hud"></div>
<script>
element = document.querySelector('.hud');
console.log(element);
// reset the transition by...
element.addEventListener("click", function(e) {
console.log("clicked");
e.preventDefault;
element.classList.remove("anim");
void element.offsetWidth;
element.classList.add("anim");
}, false);
</script>
</body>
</html>
Was it so necessary for you? In order for the animation in your example to work constantly, a reset function is needed.
element = document.querySelector('#red_box');
console.log(element);
element.addEventListener("click", function(e) {
e.preventDefault;
console.log("clicked");
element.classList.remove("hud");
element.classList.remove("anim");
void element.offsetWidth;
element.classList.add("anim");
}, false);
/*$(".hud").click(function () {
var $this = $(this);
$this = reset($this);
$this.addClass("anim bounceIn_1");
console.log("clicked");
});*/
.anim {
width: 100px;
height: 100px;
background-color: red;
animation-name: bounceIn_1;
animation-duration: .5s;
}
.hud {
width: 100px;
height: 100px;
background-color: red;
animation-name: fade-in;
animation-duration: .5s;
}
#-webkit-keyframes fade-in {
0% {
opacity: 0; }
100% {
opacity: 1; } }
#-webkit-keyframes bounceIn_1 {0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scaleX(1);transform:scaleX(1)}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<p>This box should fade in and bounce on click</p>
<div id="red_box" class="hud"></div>
</body>
Have you tried to put a comma in your .anim class?
animation: bounceIn_1 .5s, fade-in .5s
You need to put the 2 animation in the same css class and make sure that the removing and the adding of that class are done in 2 separate frames.
The first issue can be easily solved by putting a comma between the 2 animations which are now in the class .anim.
The second issue is a little bit tricky but the window.requestAnimationFrame() function will solve it !
Here you have the modified code so that you can better understand:
element = document.querySelector('.hud');
console.log(element);
// reset the transition by...
element.addEventListener("click", function(e) {
console.log("clicked");
e.preventDefault;
element.classList.remove("anim");
void element.offsetWidth;
window.requestAnimationFrame(() => element.classList.add("anim")); /* The add() will be done before the next repaint so that we can see the change */
}, false);
.anim {
animation-name: fade-in, bounceIn_1;
animation-duration: .5s;
}
.hud {
width: 100px;
height: 100px;
background-color: red;
//animation-name: fade-in; /* Remove this */
//animation-duration: .5s; /* Remove this */
}
#-webkit-keyframes fade-in {
0% {
opacity: 0; }
100% {
opacity: 1; } }
#-webkit-keyframes bounceIn_1{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scaleX(1);transform:scaleX(1)}}
<body>
<p>This box should fade in and bounce on click</p>
<div class="hud"></div>
</body>
Quick tip: with this method you can play as many animation as you want on the same element, just add its name to the .anim animations list and you're done!
Naturally, we can create a CSS animation using keyframes, and control it from there.
However, ideally, I would like to trigger this animation from a button click - so the button click would be an event...
#keyframes fade-in {
0% {opacity: 0;}
100% {opacity: 1;}
}
Now, on click, I want to trigger this animation; as opposed to from within the CSS animation property.
see here jsfiddle
if you want your animation to work every time you press the button use this code :
$('button').click(function() {
$(".fademe").addClass('animated');
setTimeout(function() {
$(".fademe").removeClass('animated');
}, 1500);
});
where 1500 is the animation-duration in this case, 1.5s
$('button').click(function() {
$(".fademe").addClass('animated');
setTimeout(function() {
$(".fademe").removeClass('animated');
}, 1500);
});
.fademe {
width: 100px;
height: 100px;
background: red;
}
.fademe.animated {
animation: fade-in 1.5s ease;
}
#keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="fademe">
</div>
<button>CLICK ME</button>
EXPLANATION :
on click on the button add class animated ( or any other class ) to the element you want to apply the animation to , .fademe
make a setTimeout(function() to delay the removeClass for the duration of the animation 1.5s or 1500ms
write in CSS the declaration of the animation , #keyframes, and add it to the element with the class added by the JQ .fademe.animated
$("#move-button").on("click", function(){
$("#ship").removeClass("moving");
$("#ship")[0].offsetWidth = $("#ship")[0].offsetWidth;
$("#ship").addClass("moving");
});//
#ship
{
background: green;
color: #fff;
height: 60px;
line-height: 60px;
text-align: center;
width: 100px;
}
#move-button
{
margin-top: 20px;
}
#ship.moving
{
animation: moving 2s ease;
}
#keyframes moving
{
0%{ transform: translate(0px);}
50%{ transform: translate(20px);}
100%{ transform: translate(0px);}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="ship">Ship</div>
<button id="move-button">Push</button>
If you want to make the animation happen and always end before allowing the event listener to trigger it again, I would suggest to control the behaviour like this:
// Add this to your event listener
if (!element.classList.contains("myClass")) {
element.className = "myClass";
setTimeout(function() {
element.classList.remove("myClass");
}, 1000); //At least the time the animation lasts
}
There is a toggle method that works just fine for this, hope it helps:
function Fade() {
document.getElementById("box").classList.toggle("animate");
}
#box {
background-color: black;
height: 50px;
width: 50px;
}
.animate {
animation: fademe 0.5s;
}
#keyframes fademe {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<html>
<head>
<title>
Animation Trigger
</title>
</head>
<body>
<div id="box"></div>
<button onclick="Fade()"> Fade above Box</button>
</body>
I want to know if there is a way to make an HTML element disappear with an animation of CSS. So when the element gets removed from the page by some script, an animation shall display before the element actually gets removed.
Is this possible in an easy way? Or do I need to set a timer to my script that starts the animation with a duration of X and removes the element after time X?
I would get fancy with keyframes
#keyframes myAnimation{
0%{
opacity: 1;
transform: rotateX(90deg);
}
50%{
opacity: 0.5;
transform: rotateX(0deg);
}
100%{
display: none;
opacity: 0;
transform: rotateX(90deg);
}
}
#myelement{
animation-name: myAnimation;
animation-duration: 2000ms;
animation-fill-mode: forwards;
}
If the script is actually removing the DOM element, I don't believe there's a way to fade it out. I think the timer is your only option.
I use jQuery to implement this.
//jQuery
$(document).ready(function() {
var target = $("#div");
$("#btn").click(function() {
removeElement(target);
});
});
function removeElement(target) {
target.animate({
opacity: "-=1"
}, 1000, function() {
target.remove();
});
}
div {
width: 100px;
height: 100px;
background-color: #000;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body>
<div id="div"></div>
<input type="button" value="fadeout" id="btn">
</body>
</html>
Use transitions like this:
function waithide()
{
var obj = document.getElementById("thisone");
obj.style.opacity = '0';
window.setTimeout(
function removethis()
{
obj.style.display='none';
}, 300);
}
div
{
height:100px;
width :100px;
background:red;
display:block;
opacity:1;
transition : all .3s;
-wekit-transition : all .3s;
-moz-transition : all .3s;
}
<div id="thisone" onclick="waithide()"></div>
I think you would have to do it in two steps. first the animate. Then, after animate is done, remove the elem. See the function below. Perhaps it could be put in a jquery plugin?
<style>
#test{
background: red;
height: 100px;
width: 400px;
transition: height 1s;
}
#test.hide {
height: 0;
}
</style>
<div id="test"> </div>
<button>Hide the Div</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js"></script>
<script>
$('button').click(function(){
removeWithAnimate('#test');
});
function removeWithAnimate(id){
$(id).addClass('hide');
setTimeout( function(){
$(id).remove()
},1000);;
}
</script>
$('button').click(function() {
removeWithAnimate('#test');
});
function removeWithAnimate(id) {
$(id).addClass('hide');
setTimeout(function() {
$(id).remove()
}, 1000);;
}
#test {
background: red;
height: 100px;
width: 400px;
transition: height 1s;
}
#test.hide {
height: 0;
}
<div id="test"> </div>
<button>Hide the Div</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.js"></script>
transition: .5s;
invisible:
opacity: 0;
visible:
opacity: 1;
transition will make it appear and disappear smoothly.
So, I have created a CSS3 animation that is supposed to fade out an element by setting its opacity from 1 to 0 and at the last frames change the position to absolute and display to none. But on Safari it will only maintain the opacity, position and display are not set to the final values.
#-webkit-keyframes impressum-fade-out {
0% {
opacity: 1;
display: block;
position: relative;
}
99% {
opacity: 0;
position: relative;
}
100% {
opacity: 0;
display: none;
position: absolute;
}
}
It seems to work on Chrome but not on Safari (I tried version 8). Apparently, position and display do not work properly with animation-fill-mode: forwards...
JSFiddle: http://jsfiddle.net/uhtL12gv/
EDIT For Bounty: I am aware of workarounds with Javascript and transitionend events. But I am wondering why Browsers lack support for this? Does the specification state that fillmode forwards doesnt apply to some attributes like position or is this a bug in the browsers? Because I couldnt find anything in the bug trackers.. If anybody has some insight, I would really appreciate it
As Suggested in the comments, you can adjust the height.
EDIT: Animation Reference Links Added.
Display property is not animatable.
Position property is not
animatable.
List of all CSS properties and if and how they are
animatable.
$('.block').click(function() { $(this).toggleClass('active') });
#-webkit-keyframes impressum-fade-out {
0% {
opacity: 1;
}
99% {
opacity: 0;
}
100% {
opacity: 0;
height:0;
}
}
.block {
width: 100px;
height: 100px;
background: blue;
}
.block2 {
width: 100px;
height: 100px;
background: red;
}
.block.active {
-webkit-animation-name: impressum-fade-out;
animation-name: impressum-fade-out;
-webkit-animation-duration: 500ms;
animation-duration: 500ms;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="block"></div>
<div class="block2"></div>
I would suggest you the cross-browser solution based on CSS3 Transitions and transitionend event:
JSFiddle
$('.block').one('click', function() {
var $this = $(this);
$this.one('webkitTransitionEnd transitionend', function() {
$this.addClass('block_hidden');
$this.removeClass('block_transition');
});
$this.addClass('block_transition');
});
.block {
width: 100px;
height: 100px;
background: blue;
-webkit-transition: opacity 0.5s;
transition: opacity 0.5s;
}
.block_2 {
background: red;
}
.block_transition {
opacity: 0;
}
.block_hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="block"></div>
<div class="block block_2"></div>