Can't change css animation duration css on body with jQuery
I have a CSS animation running on a body element that has a default duration of 20 seconds. I want this to be able to be changed with user input, but I can't seem to get it to work.
By default, I have CSS:
body {
...
animation: MoveBG 20s ease infinite;
}
If I run this jQuery code:
$('body').css('animation', 'MoveBG 2s ease infinite');
The animation will have a duration of 20 seconds. The funny thing is that if I run:
alert($('body').css('animation-duration'));
He will tell me that the animation duration is 2 seconds (which is clearly not the case).
// the animation duration should change to 2s, but it still animates at 20s
var animation = 'MoveBG 2s ease infinite';
$('body').css('animation', animation);
// it even says that it is animate at 2s
//alert($('body').css('animation-duration'));
body {
background: linear-gradient(to right, #f00, #0f0, #00f);
background-size: 600% 100%;
-webkit-animation: MoveBG 20s ease infinite;
-moz-animation: MoveBG 20s ease infinite;
-o-animation: MoveBG 20s ease infinite;
animation: MoveBG 20s ease infinite;
}
@-webkit-keyframes MoveBG {
0% {
background-position: 0 0
}
50% {
background-position: 100% 0
}
100% {
background-position: 0 0
}
}
@-moz-keyframes MoveBG {
0% {
background-position: 0 0
}
50% {
background-position: 100% 0
}
100% {
background-position: 0 0
}
}
@-o-keyframes MoveBG {
0% {
background-position: 0 0
}
50% {
background-position: 100% 0
}
100% {
background-position: 0 0
}
}
@keyframes MoveBG {
0% {
background-position: 0 0
}
50% {
background-position: 100% 0
}
100% {
background-position: 0 0
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Jsfiddle: http://jsfiddle.net/sdobc5vx/2/
Anyone can figure out what I am doing wrong?
This happens to me in Chrome 37, but it looks like it works in Firefox 30. Hmm ...
source to share
Not really sure, but it looks like the frame update isn't happening even if you override an already running keyframe, possibly a chrome bug.
One trick is to hide the element and show it (asynchronously) for redrawing (but not so desirably with flickering).
$('body').css('animation', animation).hide().show(0);
//^__ Need this to force asyncronous show
var animation = 'MoveBG 2s ease infinite';
$('body').css('animation', animation).hide().show(0);
//^___Asyncronously show
body {
background: linear-gradient(to right, #f00, #0f0, #00f);
background-size: 600% 100%;
-webkit-animation: MoveBG 20s ease infinite;
-moz-animation: MoveBG 20s ease infinite;
-o-animation: MoveBG 20s ease infinite;
animation: MoveBG 20s ease infinite;
}
@-webkit-keyframes MoveBG {
0%{background-position:0 0}
50%{background-position:100% 0}
100%{background-position:0 0}
}
@-moz-keyframes MoveBG {
0%{background-position:0 0}
50%{background-position:100% 0}
100%{background-position:0 0}
}
@-o-keyframes MoveBG {
0%{background-position:0 0}
50%{background-position:100% 0}
100%{background-position:0 0}
}
@keyframes MoveBG {
0%{background-position:0 0}
50%{background-position:100% 0}
100%{background-position:0 0}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
</body>
Here's another hack that works. Reset the animation to anyone and then set it back, which really doesn't flicker.
var animation = 'MoveBG 2s ease infinite';
var $body = $('body').css('animation', 'none'); //reset it
setTimeout(function(){
$body.css('animation', animation); //set it back
});
You can use the same hack with addClass.
source to share
Change, update
Try it (workaround)
var duration = "2s";
$("body")[0].style.WebkitAnimationDuration = duration;
$("style").detach().hide(function() {
$("head").prepend(this);
});
$(function() {
var twenty = $(".twenty");
var two = $(".two");
var span = $("span");
span.prepend("<b>twenty: </b>"
+ window.getComputedStyle(twenty[0], null).WebkitAnimation
+ " <b>before</b>"
+ "<br><b>two: </b>"
+ window.getComputedStyle(two[0], null).WebkitAnimation
+ "<b> before</b>");
// the animation duration should change to 2s, but it still animates at 20s
var duration = "2s";
// $('body').css('animation', animation);
two[0].style.WebkitAnimationDuration = duration;
$("style").detach().hide(function() {
$("head").prepend(this);
});
span.append("<br><b>twenty: </b>"
+ window.getComputedStyle(twenty[0], null).WebkitAnimation
+ " <b>after</b>"
+ "<br><b>two: </b>"
+ window.getComputedStyle(two[0], null).WebkitAnimation
+ "<b> after</b>");
// it even says that it is animate at 2s
alert(two.css('animation-duration')
+ "\n"
+ window.getComputedStyle(two[0], null).webkitAnimationDuration);
});
span {
font-size : 12px;
height : 50px !important;
}
div.two {
margin-left:20px;
}
div {
display : inline-block;
position : relative;
width : 200px;
height : 400px;
background: linear-gradient(to right, #f00, #0f0, #00f);
background-size: 600% 100%;
-webkit-animation: MoveBG 20s ease infinite;
-moz-animation: MoveBG 20s ease infinite;
-o-animation: MoveBG 20s ease infinite;
animation: MoveBG 20s ease infinite;
}
@-webkit-keyframes MoveBG {
0%{background-position:0 0}
50%{background-position:100% 0}
100%{background-position:0 0}
}
@-moz-keyframes MoveBG {
0%{background-position:0 0}
50%{background-position:100% 0}
100%{background-position:0 0}
}
@-o-keyframes MoveBG {
0%{background-position:0 0}
50%{background-position:100% 0}
100%{background-position:0 0}
}
@keyframes MoveBG {
0%{background-position:0 0}
50%{background-position:100% 0}
100%{background-position:0 0}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
<span class="animations"></span><br />
<div class="twenty"></div><div class="two"></div>
</body>
jsfiddle http://jsfiddle.net/sdobc5vx/31/
source to share
I tried it in Safari, everything is fine. Chrome isn't responding to anything.
Try this, see if it changes:
$('body').css({
-webkit-animation: animation,
-moz-animation: animation,
-o-animation: animation,
animation: animation,
});
source to share