I have a very strange issue. I'm loading articles from JSON in jQuery and as they load, I'd like to add a class of 'animate' to each dynamic element.
$.each(jsonArticles, function (i, article) {
var $articleHTML = $(
'<article class="article">' +
'<a href="' + jsonObject.filmLink + article.reviewLink + '"><img src="' + jsonObject.imagePath + article.reviewImage + '" alt=""></a>' +
'<h1><a href="' + jsonObject.filmLink + article.reviewLink + '">' + article.reviewTitle + '</a></h1>' +
'<p><a href="' + jsonObject.filmLink + article.reviewLink + '">' + article.reviewSummary + '</a></p>' +
'</article>');
$articles
.append($articleHTML)
.find("article")
.addClass("animate");
});
All of this works great and checking in Firebug reveals that the class is successfully added to each article tag.
However, when trying to use a CSS transition on the article for the class that's added, it does not animate, but instead skips straight to the final style (opacity: 1).
.article {
opacity: 0;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.article.animate {
opacity: 1;
}
The animation doesn't happen, but the class is added and the article is successfully set to opacity: 1. It shows up instantly.
Anyone have any ideas about this? I cannot figure this one out at all.
On another point, which is rather interesting...if I change the .animate
class to have a :hover
, then the articles won't show until I hover and the animation does work. Why it would work for hover and not when it's simply added immediately, seems strange to me.
.article.animate:hover {
opacity: 1;
}
I'd appreciate any input.
Thanks, Mikey.
Live Demo: http://jsfiddle.net/Pz5CD/ Notice how the articles just pop in at 100% opacity. No animation is seen.
It turns out the OP wants to fade in each element sequentially, which is beyond the scope of the original question. I'll leave my answer here as an answer to the original question.
The issue is that your new html is added to the page and the animate
class is added before the css for that html has been applied. The browser will skip ahead like that for the sake of efficiency. For example, if you added a class, then removed it, and repeated that process a hundred times, there wouldn't be a visual difference. It would have just skipped to the result. For this reason, you have to force a redraw on the element so that all previous styles have applied before adding the class. I wrote a function to handle this that should work in every circumstance on every browser, though there's no way to guarantee the behavior of a reDraw. It probably will always work and it's nice to have!
Live demo here (click). You can tell the reDraw is making the difference by commenting it out and just leaving the addClass()
.
$('body').append($articleHTML);
$a = $('body').find("article");
reDraw($a).then(function() {
$a.addClass("animate");
});
function reDraw($element) {
var deferred = new $.Deferred();
setTimeout(function() {
var h = $element[0].offsetHeight;
var s = $element[0].getComputedStyle;
deferred.resolve();
},0);
return deferred.promise();
}
The best way to force a redraw is to either access the offsetHeight
or getComputedStyle
of an element. However, there have been cases where those have failed for force a redraw on certain mobile devices. To add some extra encouragement for a redraw, I added a setTimeout
as well. Even a time of 0 on the timeout will work, but it throws off the call stack, so I use a promise to ensure the next operation (adding your class) will happen after the redraw. That just means you'll use the syntax I demonstrated above to add the class - redraw($element).then(function() { //your code
For fun, I made a little demo of flipping classes with and without reDraw. http://jsbin.com/EjArIrik/1/edit
You need to add the class to the element after it is rendered to the dom, a set timout might work
setTimeout(function(){
$articleHTML.addClass("animate");
}, i * 500 );
http://jsfiddle.net/Pz5CD/1/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With