CSS过渡在子元素上,当父元素切换显示属性时

5
我看到了这个链接:SO css-transition-from-display-none-on-class-change,但是我想在父元素上切换显示属性。有没有一种方法可以使它起作用?
CSS过渡效果的工作原理如下:fiddle https://jsfiddle.net/v1aym7wd/ HTML:
<div id="wrap">
    <div class="fade"></div>
</div>

CSS:
#wrap {
    background-color: orange;
    width: 200px;
    height: 200px;
    /*display: none;*/
}

#wrap.show {
    /*display: block;*/
}

.fade {
    background-color: green;
    width: 100px;
    height: 100px;
    opacity: 0.2;
    transition: opacity 10s;
}

#wrap.show .fade {
    opacity: 1;
}

JS:

var wrap = document.getElementById('wrap');
wrap.classList.add('show');

但是,一旦我在父元素上切换display:block/none,CSS过渡就不起作用了。为什么会这样?有什么方法可以让它工作吗? 点击此处查看示例:https://jsfiddle.net/v1aym7wd/1/

3
当您将“display:none”应用于父元素时,子元素也不会在屏幕上显示... 所以我猜过渡效果也不会起作用... - kukkuz
1
如果你可以使用visibility而不是display,它应该可以工作。(如果你不能使用visibility:hidden来保留元素所需的空间效果,那么尝试将其与宽度/高度0和溢出设置为hidden相结合。) - CBroe
1
当然。Fiddle。我不知道为什么显示不可过渡。所以我不会在下面添加这个。我设置了一个超时,只是让你知道它在显示更改时启动。 - AA2992
2
如果您在包装器上使用一个类,另一个类用于淡出元素,并分别添加它们,则也可以正常工作:https://jsfiddle.net/v1aym7wd/5/ - CBroe
2
“即使我们不知道为什么” - 我们知道,@kukkuz在第一条评论中提到的是原因。浏览器不会呈现具有display:none属性的元素或其任何子元素 - 就呈现而言,它们的行为就像它们甚至不是DOM树的一部分一样。因此,您的淡入元素没有设置初始值的不透明度。当#wrap添加了“show”类时,它立即获得不透明度值1 - 因此,在这种情况下没有任何过渡效果。 - CBroe
显示剩余6条评论
3个回答

13

由于在父元素上使用 display:none 也会将后代元素从DOM树中移除,因此一种解决方案是放弃过渡效果并改用动画。

当子元素显示时,动画将启动。

请务必使用必要的供应商前缀。

.fade {
  opacity: 0.2
}

#wrap.show .fade {
  animation: reveal 10s forwards;
}

@keyframes reveal {
  100% {
    opacity: 1
  }
}

/* set timeout to show how animation starts. */

setTimeout(function reveal() {
  var wrap = document.getElementById('wrap');
  wrap.classList.add('show');
}, 2000);
#wrap {
  background-color: orange;
  width: 200px;
  height: 200px;
  display: none;
}

#wrap.show {
  display: block
}

.fade {
  background-color: green;
  width: 100px;
  height: 100px;
  opacity: 0.2
}

#wrap.show .fade {
  animation: reveal 10s forwards;
}

@keyframes reveal {
  100% {
    opacity: 1
  }
}
<div id="wrap">
  <div class="fade"></div>
</div>


为什么我从来没有想到过那个!这是一个很好的解决旧问题的方法。 - Nickfmc

5
如CBroe所说,可以使用visibility而不是display来实现。 https://jsfiddle.net/ryanoconr/v1aym7wd/2/

var wrap = document.getElementById('wrap');

wrap.classList.add('show');
#wrap {
    background-color: orange;
    width: 200px;
    height: 200px;
    display: block;
    visibility: hidden;
}

#wrap.show {
  visibility: visible;
}

.fade {
    background-color: green;
    width: 100px;
    height: 100px;
    opacity: 0.2;
    transition: opacity 10s;
}

#wrap.show .fade {
    opacity: 1;
}
<div id="wrap">
    <div class="fade"></div>
</div>

代码在片段中似乎无法工作,但在 JSFiddle 上可以工作。

很遗憾,我没有足够快的速度查看所有的评论和答案,因此无法将display属性更改为visible - caramba
如果您无法从显示更改为可见性,那么我目前能想到的唯一方法就是在父级元素上同时更改不透明度和显示属性。 - Ryan O'Connor
感谢你的帮助:Ankith在评论中为我提供了可行的解决方案:请见此处 - caramba

-1

试试这个:

setTimeout(function(){
    var wrap = document.getElementById('wrap');
    wrap.classList.add('show');
  },1000);
#wrap {
    background-color: orange;
    width: 200px;
    height: 200px;
    opacity: 0;
}

#wrap.show {
   opacity: 1;
}

.fade {
    background-color: green;
    width: 100px;
    height: 100px;
    opacity: 0.2;
    transition: opacity 10s;
}

#wrap.show .fade {
    opacity: 1;
}
<div id="wrap">
    <div class="fade"></div>
</div>


除了 setTimeOut 和注释的删除之外,与我上面创建的第一个示例(https://jsfiddle.net/v1aym7wd/)没有任何区别。因此没有任何有帮助的更改。 - caramba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接