I'm currently designing a kind of CSS 'mega dropdown' menu - basically a normal CSS-only dropdown menu, but one that contains different types of content.
At the moment, it appears that CSS3 Transitions don't apply to the 'display' property, i.e. you can't do any sort of transition from display: none
to display: block
(or any combination).
Can anyone think of a way for the second-tier menu from the above example to 'fade in' when someone hovers over one of the top level menu items?
I'm aware that you can use transitions on the visibility:
property, but I can't think of a way to utilise that effectively.
I've also tried using height but that just failed miserably.
I'm also aware that it's trivial to achieve this using JavaScript, but I wanted to challenge myself to use just CSS and I think I'm coming up a little short.
All and any suggestions most welcome.
You can get this to work the natural way you expected - using display - but you have to throttle the browser to get it to work, using either JS or as others have suggested a fancy trick with one tag inside another. I don't care for the inner tag as it further complicates CSS and dimensions, so here's the JS solution:
https://jsfiddle.net/b9chris/hweyecu4/1/
Starting with a box like:
A hidden box. You can have it transition on click with:
The CSS is what you'd guess:
The key is throttling the display property. By removing the hidden class then waiting 50ms, then starting the transition via the added class, we get it to appear and then expand like we wanted, instead of it just blipping onto the screen without any animation. Similar occurs going the other way, except we wait till the animation is over before applying hidden.
Note: I'm abusing
.animate(maxWidth)
here to avoidsetTimeout
race conditions.setTimeout
is quick to introduce hidden bugs when you or someone else picks up code unaware of it..animate()
can easily be killed with.stop()
. I'm just using it to put a 50ms or 2000ms delay on the standard fx queue where it's easy to find/resolve by other coders building on top of this.If you are using jQuery to set your classes, this will work 100%:
Of course you could just use jQuery
.fadeIn()
and.fadeOut()
functions, but the advantage of setting classes instead is in case you want to transition to a display value other thanblock
(as is the default with.fadeIn()
and.fadeOut()
).Here I am transitioning to display
flex
with a nice fade effect.At the time of this post all major browsers disable CSS transitions if you try to change the
display
property, but CSS animations still work fine so we can use them as a work-around.Example Code:- (You can apply it to your menu accordingly) Demo
Add the following CSS to your stylesheet:-
Then apply the
fadeIn
animation to the child on parent hover:- (and of course setdisplay: block
)According to W3C Working Draft 19 November 2013
display
is not an animatable property. Fortunately,visibility
is animatable. You may chain its transition with a transition of opacity (JSFiddle):HTML:
CSS:
JavaScript for testing:
Note that if you just make the link transparent, without setting
visibility: hidden
, then it would stay clickable.Edit: display none is not being applied in this example.
What's happening above is that through 99% of the animation display is set to block while the opacity fades out. In the last moment display property is set to none.
And the most important bit is to retain the last frame after the animation ends using animation-fill-mode: forwards
Here are two examples: https://jsfiddle.net/qwnz9tqg/3/
You can simply use css visibility: hidden/visible instead of display : none/block