0

I have two divs. One fills the page, the other is hidden and gets displayed with a CSS3 animation :

div{
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
}
.div2{
    top:100%;
    display:none;
    transition: top  0.3s ease-in-out;
}
.div2.shown{
    top:0;
}

Now, I know that I cannot put display:block directly inside the .shown class because it is not supported by CSS 3 animations.

So here is what I do :

$(".div2").show().toggleClass("shown");

But the animation does not work, it just appears instantly. I thought that it was because the .show() wasn't finished yet when I trigger toggleClass. So, as a "duration" method, it must support .delay.

Now, if I delay the toggleClass :

$(".div2").show().delay(100).toggleClass("shown");

Still does not work. Let's try a setTimeout:

$(".div2").show(); 
setTimeout(function(){$(".div2").toggleClass("shown")}, 1);

This one works. So it appears that show() is indeed a long operation, but it does not support the delay() method. So I wanted to try using its callback :

$(".div2").show(function(){$(".div2").toggleClass("shown")});

And this works, without setTimeout ! But the callback gets called twice (once at the beginning, once 400ms after). What should I use to do that properly ?

Rayjax
  • 7,494
  • 11
  • 56
  • 82
  • 2
    The `display` property can't be animated, neither in CSS or in JS, as it only has string values. You can however animate opacity – adeneo Mar 02 '15 at 15:27
  • Of course, and I do not even need to animate the display prop, nor use opacity or visibility. What I want is to apply display:block, and then move the div with the css3 animation. I would like to do this without using setTimeout – Rayjax Mar 02 '15 at 15:31
  • 1
    @gmo That is not correct. With no parameters `show` is not an animation at all. This is spelled out in the documentation. That 400ms default only applies to the version with paramters. So if you apply a callback but no duration, then you get 400ms. – James Montagne Mar 02 '15 at 15:36
  • If you just want to show the element, and move it, add `display:block` to the `.shown` class ? – adeneo Mar 02 '15 at 15:37
  • @JamesMontagne absolutely right, comment removed. – gmo Mar 02 '15 at 15:40
  • Your last solution should work. I think your code is just a little messed up if you're getting 2 callbacks. I just threw together a test real quick and the callback only happens once: http://jsfiddle.net/fxLf8s62/ – Chad Mar 02 '15 at 15:44
  • $(".div2").show().delay(100).queue(function() { $(this).toggleClass("shown"); }); would work as well. – lshettyl Mar 02 '15 at 15:46
  • @adeneo it does not work. I guess that as CSS3 can't animate "display", it just applies the display change once the animation is completed, thus I don't see the animation – Rayjax Mar 02 '15 at 15:46
  • @LShetty nice, I couldn't get delay() to work. But still, it makes me write down a fixed timeout, which often is a bad idea – Rayjax Mar 02 '15 at 15:47
  • @Chad in your fiddle it does log only once, but if I paste it in my console it does log twice. Using last Chrome version. wtf ? – Rayjax Mar 02 '15 at 15:50
  • @Rayjax look at your network tab and make sure you aren't loading two copies of jQuery. – Chad Mar 02 '15 at 15:52
  • @Rayjax I guess your best bet is your last option although it applies 400ms by default. I can't think of another way unless you animate opacity! – lshettyl Mar 02 '15 at 15:53
  • @LShetty 400 ms is there indeed http://jsfiddle.net/Rayjax/fxLf8s62/1/. The timestamp displays between 405 and 415 on my env, so the real show() must take around 15ms max. it's sad to wait 400 ms for nothing. There must be away to trigger the toggleClass just when the display is done. Opacity is not a solution because the div will still be displayed and it will take up some place at the bottom of the page – Rayjax Mar 02 '15 at 15:56
  • Slightly different so I won't close as duplicate, but this issue is addressed here: http://stackoverflow.com/questions/13451328/css-transition-on-an-initially-hidden-elemement – James Montagne Mar 02 '15 at 16:14

1 Answers1

1

Took me a second to see this. The easiest solution is just to set a timer of 0 on your $.show() command, like:

$('.div2').show(0).toggleClass('shown');

That will toggle the show instantly and allow for the animation to happen (see http://jsfiddle.net/8y4Lq2n9/).

If you're worried about setting a specific number, there are options you can pass into the show command, with the specific one being :

$('.div2').show({queue:false}).toggleClass('shown');

This will take the element out of the animation queue and allow other actions to happen instead of preventing the transitions. See: http://jsfiddle.net/8y4Lq2n9/1/

Chad
  • 5,308
  • 4
  • 24
  • 36
  • Still uses an implicit timeout, but the syntax is cleaner this way. Will wait a little to see if anyone posts another idea but for the moment this seems to be the best option – Rayjax Mar 02 '15 at 15:58