I'm having trouble creating a flyout menu with a specific effect. The flyout goes from display:none to block and then I use jquery to animate opacity from 0 to 1 (and vice versa). This is necessary because otherwise the transition does not happen when the element has just had it's display property changed. I did not think that this would propagate to children. But inside of my flyout I have 4 columns of links that have an opacity transition, each with it's own delay so they come in one at a time. However, this does not work as the flyout appears. They are instantly at opacity: 1 and even with a long delay time it still does not work.
Is there a way around this? I knew that CSS animation alongside a display change on the same element did not work, but finding out that any child animations also do not work is a little frustrating. I'd rather not have to write javascript when the CSS is so simple. But if javascript is the only answer, then that will be an easy solve.
Here's a very simplified example of the code:
$flyout.addClass('in').animate({opacity: 1}, 200, "linear");
"in" is the class that causes the transition on the columns:
.flyout { display: none; }
.flyout.in { display: block; }
.columns li {
opacity: 0;
-webkit-transition: opacity 0.2s;
}
.flyout.in .columns li { opacity: 1; }
// delay increases with each column
.columns > li:first-child {
-webkit-transition-delay: 0.2s;
}
@rodneyrehm's answer pretty much sums up everything you need when handling animations with css display property.
You need to trigger a reflow after toggling the display property and apply an animation class after it.
if you want only to change the
opacity
you can use FadeIn and FadeOut functions of JQuery but if you want more complex transition you can use CSS3 (this is a realy good library). See this DEMO where you can see this two different way.You can also add a controll to the class like this:
to make two way functions.
It does not only apply to the same element, but the entire sub-tree - as the entire sub-tree is not rendered.
display: block
on the wrapper, then force a reflow (by flushing the style buffer withwrapperElement.offsetHeight;
), then add a class that setsopacity:1
to your children (or do whatever you're doing to kick off the animations).width: 0; height: 0; overflow: hidden; visibility: hidden;
(or, for nicer transitionstransform: scale(0); visibility: hidden; pointer-events: none;
)As soon as
display:none
is involved, you're screwed when it comes to transitions. The best way is to avoid it. I've been using the second option without any significant problems for quite a while now.edit after OP added some demo code:
.animate()
of the wrapper can be done in CSS as well-webkit-transition
, but the propertransition
as well// delay increases with each column
looks like a misconception. all elements the selector.columns > li:first-child
applies to will have the exact same delay - they won't wait for the previous element to finish its transition. If you want to define that in CSS, you'll have to play with :nth-child() or one of its cousinsI went into this same problem a while ago, my workaround was very hacky but mostly works
When you change a, lets say, non transitionable property, like 'display' thing go wrong really fast, i figured that if you use a timmer to change the not transitionable property and a few miliseconds later you change another transitionable property, it kind of works, an you also need to use another timer for turning things back
The HTML
The CSS
jQuery for handlig the states of the mouse
And here is a working example https://codepen.io/Teobis/pen/QxmqGQ
Hope this helps