CSS display属性的转换

1932

我目前正在设计一个CSS“超级下拉”菜单-基本上是一个常规的仅使用CSS的下拉菜单,但其中包含不同类型的内容。

目前看来, CSS 3转换不适用于“display”属性,也就是说,您无法从“display: none”到“display: block”(或任何组合)进行任何过渡。

是否有一种方法可以使上面示例中的二级菜单在某人悬停在顶级菜单项上时“淡入”?

我知道您可以在“visibility:”属性上使用过渡,但我无法想出有效使用它的方法。

我还尝试使用高度,但那样只会失败。

我知道使用JavaScript轻松实现这一点,但我想挑战自己仅使用CSS,并且我认为我做得不够好。


32
position: absolute; visibility: hidden;与display: none;相同。 - Jawad
13
只有当你添加类似于 z-index:0 的内容时才行。 - DanMan
31
建议永远不要使用 visibility: hidden,除非你希望屏幕阅读器读取它(而典型的浏览器不会)。它仅定义元素的可见性(就像说 opacity: 0 一样),它仍然是可选、可点击和以前的任何状态;它只是不可见。 - Forest Katsch
2
IE 8、9、10不支持pointer-events,因此并不总是可行。 - Steven Pribilinskiy
5
你需要使用“display: none”,否则你可能会意外地显示隐藏的对象,而这些对象在触发器外面,我只是提醒一下 :) - Samuel Ramzan
显示剩余7条评论
40个回答

22

编辑:在这个例子中,display:none 没有被应用。

@keyframes hide {
  0% {
    display: block;
    opacity: 1;
  }
  99% {
    display: block;
  }
  100% {
    display: none;
    opacity: 0;
  }
}

上面所发生的是,在99%的动画显示中,它的display属性被设置为block,同时不透明度会逐渐消失。在最后一刻,display属性被设置为none。

而最重要的部分是,使用animation-fill-mode: forwards来保留动画结束后的最后一帧。

.hide {
   animation: hide 1s linear;
   animation-fill-mode: forwards;
}

以下是两个例子:https://jsfiddle.net/qwnz9tqg/3/


1
你可以将 display:block 替换为 position:initial;top:initial;,将 display:none 替换为 position:fixed;top:-1000vh;,这样就可以正常工作了。(使用 fixed 将其移出屏幕并超出正常流程基本上与 display:none 相同。) - Nexarius
它仍然在流程中保留了块空间,因此它实际上与“visibility”相同;如果您对两个应该替换彼此的页面执行此操作,则无法正常工作,因为空白空间会保留。 - Greg Wozniak

17

我的巧妙JavaScript技巧是把整个场景分成两个不同的函数

为了准备好事情,需要声明一个全局变量并定义一个事件处理程序:

  var tTimeout;
  element.addEventListener("transitionend", afterTransition, true);//firefox
  element.addEventListener("webkitTransitionEnd", afterTransition, true);//chrome

然后,当隐藏元素时,我会使用类似以下的代码:

function hide(){
  element.style.opacity = 0;
}

function afterTransition(){
  element.style.display = 'none';
}

为了让元素重新出现,我正在做如下操作:

function show(){
  element.style.display = 'block';
  tTimeout = setTimeout(timeoutShow, 100);
}

function timeoutShow(){
  element.style.opacity = 1;
}

目前为止,它能够正常工作!


16

今天我遇到了一个问题,我正在重复使用一个position: fixed的模态框。我无法将其设置为display:none,然后再进行动画处理,因为它会突然出现,并且z-index(负值等)也会发生奇怪的事情。

我还使用了height:0height:100%,但是它只在模态框出现时起作用。这与使用left:-100%或类似的效果相同。

然后我想到了一个简单的答案。看这里:

首先,你的隐藏模态框。请注意height0,并检查在过渡中的height声明……它有一个500ms比我的opacity过渡时间长。请记住,这会影响退出淡出过渡:将模态框返回到其默认状态。

#modal-overlay {
    background: #999;
    background: rgba(33,33,33,.2);
    display: block;
    overflow: hidden;
    height: 0;
    width: 100%;
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0;
    z-index: 1;
    -webkit-transition: height 0s 500ms, opacity 300ms ease-in-out;
       -moz-transition: height 0s 500ms, opacity 300ms ease-in-out;
            -ms-transition: height 0s 500ms, opacity 300ms ease-in-out;
         -o-transition: height 0s 500ms, opacity 300ms ease-in-out;
        transition: height 0s 500ms, opacity 300ms ease-in-out;
}

其次,你的可见模态框。假设你将 .modal-active 设置到 body 上。现在 height100%,并且我的过渡也已经改变了。我希望 height 立即改变,并且 opacity 花费 300ms 时间进行过渡。

.modal-active #modal-overlay {
    height: 100%;
    opacity: 1;
    z-index: 90000;
    -webkit-transition: height 0s, opacity 300ms ease-in-out;
       -moz-transition: height 0s, opacity 300ms ease-in-out;
        -ms-transition: height 0s, opacity 300ms ease-in-out;
         -o-transition: height 0s, opacity 300ms ease-in-out;
            transition: height 0s, opacity 300ms ease-in-out;
}

就是这样,它像魔法一样工作。


12

参考之前的一些答案和其他建议,以下代码非常适用于悬停菜单(我正在使用Bootstrap 3):

nav .dropdown-menu {
    display: block;
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transition: max-height 500ms, opacity 300ms;
    -webkit-transition: max-height 500ms, opacity 300ms;
}
nav .dropdown:hover .dropdown-menu {
    max-height: 500px;
    opacity: 1;
    transition: max-height 0, opacity 300ms;
    -webkit-transition: max-height 0, opacity 300ms;
}

如果您同时指定heightmax-height的值,可以使用height替换max-height,因为height:auto不能与transition一起使用。最大高度的鼠标悬停值需要大于菜单可能的height


10
我遇到过这个问题多次,现在我采用了以下方法:

.block {
  opacity: 1;
  transition: opacity 250ms ease;
}

.block--invisible {
  pointer-events: none;
  opacity: 0;
}

通过添加类block--invisible,整个元素将不可点击,但由于所有主要浏览器都支持的pointer-events:none,它后面的所有元素仍然可以被点击(不包括IE < 11)。

10

这很简单,就像下面这样 :)

@keyframes fadeout {
    0% { opacity: 1; height: auto; }
    90% { opacity: 0; height: auto; }
    100% { opacity: 0; height: 0;
}
animation: fadeout linear 0.5s 1 normal forwards !important;

让它逐渐消失,然后将其设置为height 0;。此外,请确保使用forwards以便它保持在最终状态。


7

感谢所有的回答。以下是我用于类似目的的内容:过渡(transition)与动画(animation)。

例如:https://jsfiddle.net/grinevri/tcod87Le/22/

<div class="animation"></div>
<div class="transition"></div>

@keyframes animationTo {
  0% { background-color: rgba(0, 0, 0, 0.1); }
  100% { background-color: rgba(0, 0, 0, 0.5); }
}

@keyframes animationFrom {
  0% { background-color: rgba(0, 0, 0, 0.5); }
  100% { background-color: rgba(0, 0, 0, 0.1); }
}

.animation,
.transition{
  margin: 5px;
  height: 100px;
  width: 100px;
  background-color: rgba(0, 0, 0, 0.1);
}

.animation{
  animation: animationFrom 250ms;
}

.animation:hover{
  background-color: rgba(0, 0, 0, 0.5);
  animation: animationTo 250ms;
}

.transition{
  transition: background-color 250ms;
}

.transition:hover{
  background-color: rgba(0, 0, 0, 0.5);
}

7

overflow:hidden改为overflow:visible。这样效果更好。我像这样使用:

#menu ul li ul {
    background-color:#fe1c1c;
    width:85px;
    height:0px;
    opacity:0;
    box-shadow:1px 3px 10px #000000;
    border-radius:3px;
    z-index:1;
    -webkit-transition:all 0.5s ease;
    -moz-transition:all 0.6s ease;
}

#menu ul li:hover ul  {
    overflow:visible;
    opacity:1;
    height:140px;
}

visible更好,因为overflow:hidden的作用与display:none完全相同。


7
另一种在此情况下应用过渡效果的方法不使用关键帧,是将元素的宽度设置为,然后在悬停时取消设置。
.className{
  visibility:hidden;
  opacity: 0;
  transition: .2s;
  width:0;
}

.className:hover{
  visibility:visible;
  margin-right: .5rem;
  opacity: 1;
  width:unset;
}

6
在Guillermo的回答被接受后,2012-04-03年的CSS转换规范改变了visibility转换的行为,现在可以更短地解决这个问题,而不需要使用transition-delay。
.myclass > div {
                   transition:visibility 1s, opacity 1s;
                   visibility:hidden;  opacity:0
               }
.myclass:hover > div
               {   visibility:visible; opacity:1 }

两个过渡的运行时间通常应该相同(尽管对于可见性来说略长一点并不是问题)。

有关运行版本,请参阅我的博客文章CSS Transition Visibility

关于问题标题"Transitions on the display: property"以及对Rui Marques和josh的评论的回应:

此解决方案适用于无论使用display还是visibility属性都没有影响的情况(这可能是这个问题的情况)。

它不会完全将元素删除为display:none,只是使其不可见,但仍保留在文档流中,并影响后续元素的位置。

可以使用高度(如其他答案和评论所示),最大高度或上/下边距来完成完全删除元素的过渡,类似于display:none,但也请参阅我的博客文章Workarounds for CSS Transitions on the Display and Height Properties以及How can I transition height: 0; to height: auto; using CSS?

针对GeorgeMillo的评论: 需要使用两个属性和两个过渡:不透明度属性用于创建淡入淡出动画,可见性属性用于避免元素仍对鼠标事件产生反应。在不透明度上需要过渡以获得视觉效果,在可见性上需要过渡以延迟隐藏,直到淡出完成。


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