Transitions on the CSS display property

ID : 587

viewed : 232

Tags : csscss-transitionscss

Top 5 Answer for Transitions on the CSS display property

vote vote

100

You can concatenate two transitions or more, and visibility is what comes handy this time.

div {    border: 1px solid #eee;  }  div > ul {    visibility: hidden;    opacity: 0;    transition: visibility 0s, opacity 0.5s linear;  }  div:hover > ul {    visibility: visible;    opacity: 1;  }
<div>    <ul>      <li>Item 1</li>      <li>Item 2</li>      <li>Item 3</li>    </ul>  </div>

(Don't forget the vendor prefixes to the transition property.)

More details are in this article.

vote vote

90

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; } 
vote vote

80

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; } 

Update 2019 - 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>

vote vote

64

Instead of callbacks, which don't exist in CSS, we can use transition-delay property.

#selector {     overflow: hidden;  /* Hide the element content, while height = 0 */     height: 0;     opacity: 0;     transition: height 0ms 400ms, opacity 400ms 0ms; } #selector.visible {     height: auto; opacity: 1;     transition: height 0ms 0ms, opacity 600ms 0ms; } 

So, what's going on here?

  1. When visible class is added, both height and opacity start animation without delay (0 ms), though height takes 0 ms to complete animation (equivalent of display: block) and opacity takes 600 ms.

  2. When visible class is removed, opacity starts animation (0 ms delay, 400 ms duration), and height waits 400 ms and only then instantly (0 ms) restores initial value (equivalent of display: none in the animation callback).

Note, this approach is better than ones using visibility. In such cases, the element still occupies the space on the page, and it's not always suitable.

For more examples please refer to this article.

vote vote

60

I suspect that the reason that transitions are disabled if display is changed is because of what display actually does. It does not change anything that could conceivably be smoothly animated.

display: none; and visibility: hidden; are two entirely different things.
Both do have the effect of making the element invisible, but with visibility: hidden; it’s still rendered in the layout, but just not visibly so.
The hidden element still takes up space, and is still rendered inline or as a block or block-inline or table or whatever the display element tells it to render as, and takes up space accordingly.
Other elements do not automatically move to occupy that space. The hidden element just doesn’t render its actual pixels to the output.

display: none on the other hand actually prevents the element from rendering entirely.
It does not take up any layout space.
Other elements that would’ve occupied some or all of the space taken up by this element now adjust to occupy that space, as if the element simply did not exist at all.

display is not just another visual attribute.
It establishes the entire rendering mode of the element, such as whether it’s a block, inline, inline-block, table, table-row, table-cell, list-item, or whatever!
Each of those have very different layout ramifications, and there would be no reasonable way to animate or smoothly transition them (try to imagine a smooth transition from block to inline or vice-versa, for instance!).

This is why transitions are disabled if display changes (even if the change is to or from nonenone isn’t merely invisibility, it’s its own element rendering mode that means no rendering at all!).

Top 3 video Explaining Transitions on the CSS display property

Related QUESTION?