How to create transitions on the CSS display property?

You need to hide the element by other means in order to get this to work.

I accomplished the effect by positioning both <div>s absolutely and setting the hidden one to opacity: 0.

If you even toggle the display property from none to block, your transition on other elements will not occur.

To work around this, always allow the element to be display: block, but hide the element by adjusting any of these means:

  1. Set the height to 0.
  2. Set the opacity to 0.
  3. Position the element outside of the frame of another element that has overflow: hidden.

There are likely more solutions, but you cannot perform a transition if you toggle the element to display: none. For example, you may attempt to try something like this:

div {
    display: none;
    transition: opacity 1s ease-out;
    opacity: 0;
}
div.active {
    opacity: 1;
    display: block;
}

But that will not work. From my experience, I have found this to do nothing.

Because of this, you will always need to keep the element display: block - but you could get around it by doing something like this:

div {
    transition: opacity 1s ease-out;
    opacity: 0;
    height: 0;
    overflow: hidden;
}
div.active {
    opacity: 1;
    height: auto;
}

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 workaround.

Example Code (you can apply it to your menu accordingly) Demo:

Add the following CSS to your stylesheet:

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}
@keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}

Then apply the fadeIn animation to the child on parent hover (and of course set display: block):

.parent:hover .child {
    display: block;
    -webkit-animation: fadeIn 1s;
    animation: fadeIn 1s;
}

Method that also supports fading out:

(Some JavaScript code is required)

// We need to keep track of faded in elements so we can apply fade out later in CSS
document.addEventListener('animationstart', function (e) {
  if (e.animationName === 'fade-in') {
      e.target.classList.add('did-fade-in');
  }
});

document.addEventListener('animationend', function (e) {
  if (e.animationName === 'fade-out') {
      e.target.classList.remove('did-fade-in');
   }
});
div {
    border: 5px solid;
    padding: 10px;
}

div:hover {
    border-color: red;
}

.parent .child {
  display: none;
}

.parent:hover .child {
  display: block;
  animation: fade-in 1s;
}

.parent:not(:hover) .child.did-fade-in {
  display: block;
  animation: fade-out 1s;
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fade-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
<div class="parent">
    Parent
    <div class="child">
        Child
    </div>
</div>