Sean LeBlanc Sean LeBlanc - 3 months ago 34
CSS Question

CSS transition disabled by `display:none`

I'm having an issue which seems to be preventing CSS transitions from playing on an element which is simultaneously changing from

display:none
.

In the following example, the divs have identical CSS, except that hovering over the first one hides the other two. The second div is hidden using
visibility:hidden
, and the third is hidden using
display:none
.

When you mouse over the first div, the behaviour is as expected: the first div transitions and the other two are hidden. When you mouse out, the behaviour is different from what I would expect: the first div transitions back to normal, the second div is unhidden then transitions back to normal, but the third div is unhidden and still in the normal state.

I was expecting for the third div to match the behaviour of the second and also be unhidden, then transition back to normal.



div{
width:100px;
height:50px;
background:red;

border-radius:50%;

transition: border-radius 1s;
}

#hover:hover, #hover:hover ~ div{
border-radius:0%;
}

#hover:hover ~ #hide1{
visibility:hidden;
}

#hover:hover ~ #hide2{
display:none;
}

<div id="hover">hover me for transition</div>
<div id="hide1">I transition back</div>
<div id="hide2">but I don't</div>





Since the second div works as expected, it's fairly easy to come up with alternate solutions using
visibility:hidden
and some positioning CSS, but is it possible to accomplish this in just CSS using
display:none
? If not, why does
display:none
affect other transitions in this way?

Note: This seems like something that would be easy to find, but my searches only turned up questions about attempting to transition the
display
property itself, not its side-effects on other transitions.

Answer

A simple explanation of display: none:

Turns off the display of an element (it has no effect on layout); all descendant elements also have their display turned off. The document is rendered as though the element did not exist.

(Emphasis mine)

The transition is not triggered because it was never started. The div was removed completely on hover and returned in its initial state with border-radius: 50%.

Workaround

The only possible way to achieve this affect with display: none using just CSS is to use an animation that will be triggered each time the display: none div appears.

div {
  width: 100px;
  height: 50px;
  background: red;
  border-radius: 50%;
  transition: border-radius 1s;
  animation: display 1s;
}
#hover:hover,
#hover:hover ~ div {
  border-radius: 0%;
}
#hover:hover ~ #hide1 {
  visibility: hidden;
}
#hover:hover ~ #hide2 {
  display: none;
}
@keyframes display {
  0% {
    border-radius: 0;
  }
  100% {
    border-radius: 50%;
  }
}
<div id="hover">hover me for transition</div>
<div id="hide1">I transition back</div>
<div id="hide2">but I don't (unless I have an animation)</div>