11

I have a couple of classes: hide is display: none, and transparent is opacity: 0. The element pr_container has -webkit-transition: opacity 1s. The following JQuery-based code makes an element appear in an animated fasion:

pr_container.removeClass("hide");
setTimeout(function() { pr_container.removeClass("transparent"); }, 0);

However, when I remove setTimeout and instead just remove the second class, there is no animation. Why?

Edit: I'm using the latest Chrome, I haven't checked other browsers yet.

Edit: I tried putting both calls in the same setTimeout callback - no animation. So it's clearly about separation.

Edit: here's the jsFiddle: http://jsfiddle.net/WfAVj/

Alexei Averchenko
  • 1,706
  • 1
  • 16
  • 29
  • How are you calling this code? Can you provide a jsfiddle to show what's happening? – FixMaker Feb 14 '13 at 10:48
  • @Lorax here it is: http://jsfiddle.net/WfAVj/ – Alexei Averchenko Feb 14 '13 at 11:00
  • If you are using jQuery, is there a reason you want the animation to be handled by CSS transition? Using [`.animate()`](http://api.jquery.com/animate/) or [`.fadeTo()`](http://api.jquery.com/fadeTo/) would probably yield better cross-browser functionality. – Ruben Infante Feb 14 '13 at 11:05
  • 1
    Involving `display` in transition will end up with no transition at all, AFAIK. By using `setTimeout(func,0)`, you separated the transition with `display:none`, so it works. – Passerby Feb 14 '13 at 11:06
  • @RubenInfante, that's not the point, I want to know why the browser behaves the way it does. – Alexei Averchenko Feb 14 '13 at 11:08
  • 1
    @AlexeiAverchenko That is fine, I just wanted to throw that out there given that you had only tested in Chrome. In any case, this situation would appear to have been asked/answered here: http://stackoverflow.com/a/3332179/2034234 – Ruben Infante Feb 14 '13 at 11:14
  • @AlexeiAverchenko [Cleaner solution](http://stackoverflow.com/questions/7069167/css-transition-not-firing#answer-19907889) is way better than using setTimeout, it reads propety first before changing again – vinayakj Nov 23 '15 at 19:22

4 Answers4

3

You can't make a transition if you are changing display property at the same time. So in order to make it work you have to hide your element some other way. For example:

.hide {
    height: 0;
    width: 0;
    /* overflow: hidden; padding: 0; border: none; */
}

http://jsfiddle.net/dfsq/WfAVj/1/

dfsq
  • 191,768
  • 25
  • 236
  • 258
3

There's no reasonable "curve" to transit from one display status to another, so in current implementation of browsers, any transition that somehow involves display will end up with no transition at all.

With this code:

pr_container.removeClass("hide");
pr_container.removeClass("transparent");

You can imagine the two statements execute in a single "blocking" queue, so browsers practically renders the element from class="hide transparent" to class="", and as stated above, the hide class practically invalidates any existing transition.

By using

pr_container.removeClass("hide");
setTimeout(function() { pr_container.removeClass("transparent"); }, 0);

You told browsers to remove the "transparent" class "as soon as possible, but no in the same queue", so browser first removes "hide", and then moves on. The removal of "transparent" happens when the browser think it has resource to spare, thus the transition does not get invalidated.

Passerby
  • 9,715
  • 2
  • 33
  • 50
0

only the "transperent" class produce animation .. "hide" is instant. So start the animation and if needed "hide" after 1 second:

 test.addClass("transparent");
 //hide after 1 sec, when the animation is done
 setTimeout(function() {test.addClass("hide"); }, 1000);  //1000ms = 1sec

http://jsfiddle.net/WfAVj/4/

d.raev
  • 9,216
  • 8
  • 58
  • 79
0

By using suggestions in the linked question, I made a version that I'm satisfied with:

.test {
    -webkit-transition: visibility 1s, opacity 1s;
}

.hide {
    visibility: hidden;
}

.transparent {
    opacity: 0;
}

http://jsfiddle.net/xKgjS/

Edit: now the two classes can even be combined to one!

Thanks to everyone!

Alexei Averchenko
  • 1,706
  • 1
  • 16
  • 29
  • 2
    Using `visibility:hidden` is not the same as `display:none`: http://jsfiddle.net/xKgjS/1/ But that's fine if it fits your need. – Passerby Feb 14 '13 at 11:28