CSS显示属性上的过渡

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

目前,CSS 3过渡似乎不适用于'display'属性,即,您不能进行从display: nonedisplay: block(或任何组合)的任何过渡

当有人将鼠标悬停在顶层菜单项之一上时,是否可以使上例中的第二层菜单“淡入”?

我知道您可以在visibility:属性上使用过渡,但是我想不出一种有效使用过渡的方法。

我也尝试过使用高度,但是那不幸地失败了。

我还知道使用JavaScript实现此功能很简单,但是我想挑战一下自己仅使用CSS,而且我想说的还有点不足。

2020/03/13 17:31:20

您还可以使用以下命令:

.dropdown {
    height: 0px;
    width: 0px;
    opacity: .0;
    color: white;
}
.dropdown:hover {
    height: 20px;
    width: 50px;
    opacity: 1;
    transition: opacity 200ms;
    /* Safari */
    -webkit-transition: opacity 200ms;
}
达蒙西里2020/03/13 17:31:20

您可以简单地使用CSS 可见性:隐藏/可见而不是显示:none / block

div {
    visibility:hidden;
    -webkit-transition: opacity 1s ease-out;
    -moz-transition: opacity 1s ease-out;
    -o-transition: opacity 1s ease-out;
    transition: opacity 1s ease-out;
    opacity: 0;
}

parent:hover > div {
    opacity: 1;
    visibility: visible;
}
马克2020/03/13 17:31:20

我认为SalmanPK最接近答案。它会使用以下CSS动画淡入或淡出项目。但是,显示属性不能平滑地动画,只有不透明动画。

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

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

如果要对从显示块移动到不显示的元素进行动画处理,我看不到目前仅CSS有可能。您必须获取高度并使用CSS动画来降低高度。如下面的示例所示,使用CSS可以做到这一点,但是要知道需要为元素设置动画的确切高度值将非常棘手。

jsFiddle 示例

的CSS

@-webkit-keyframes pushDown {
  0% {
    height: 10em;
  }
  25% {
    height: 7.5em;
  }
  50% {
    height: 5em;
  }
  75% {
    height: 2.5em;
  }
  100% {
    height: 0em;
  }
}

.push-down {
    -webkit-animation: pushDown 2s forwards linear;
}

的JavaScript

var element = document.getElementById("element");

// Push item down
element.className = element.className + " push-down";
2020/03/13 17:31:20

除了使用display元素外您还可以将其存储在“屏幕外”元素中,直到需要它为止,然后将其位置设置为所需的位置并同时进行变换。但是,这带来了很多其他设计问题,因此您的工作量可能会有所不同。

您可能仍然不想使用它display,因为您希望屏幕阅读器可以访问该内容,这在大多数情况下都应遵循可见性规则-即,如果眼睛不可见,它会不会显示为代理的内容。

宝儿小哥小卤蛋2020/03/13 17:31:20

我终于找到了解决方案,方法是opacity结合使用position absolute(隐藏时不占用空间)。

.toggle {
  opacity: 0;
  position: absolute;
  transition: opacity 0.8s;
}

.parent:hover .toggle {
  opacity: 1;
  position: static;
}
2020/03/13 17:31:19

该解决方案具有出色的兼容性,但我还没有看到它:

.hidden-element {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity .5s ease-out;
}

.hidden-element.visible {
  position: static;
  z-index: auto;
  pointer-events: auto;
  visibility: visible;
  opacity: 1;
}

说明:它使用了visibility: hidden技巧(与“显示并动画”一步式兼容),但是它使用了组合position: absolute; z-index: -1; pointer-events: none;来确保隐藏的容器不会占用空间并且不会响应用户交互

宝儿猿2020/03/13 17:31:19

我怀疑只要您同时修改display属性(block / none),刚开始CSS转换的任何人都会很快发现它们不起作用。尚未提及的一种解决方法是,您可以继续使用它display:block/none来隐藏/显示元素,但是可以将其不透明度设置为0,这样即使它是display:block,它仍然是不可见的。

然后淡入,添加另一个CSS类,例如“ on”,将不透明度设置为1并定义不透明度的过渡。就像您想象的那样,您必须使用JavaScript将“ on”类添加到元素中,但是至少您仍在使用CSS进行实际的过渡。

PS:如果您发现自己需要同时做这两项display:block,并同时添加“ on”类,请使用setTimeout推迟后者。否则,浏览器只会同时看到这两种情况,并禁用过渡。

西门西里2020/03/13 17:31:19

它很简单,如下所示:)

@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;另外,请确保使用转发,使其保持最终状态。

Itachi神乐2020/03/13 17:31:19

我找到了解决此问题的更好方法,您可以使用CSS动画,并使显示项目的效果很棒。

    .item {
     display: none;
}

.item:hover {
     display: block;
     animation: fade_in_show 0.5s
}

@keyframes fade_in_show {
     0% {
          opacity: 0;
          transform: scale(0)
     }
     100% {
          opacity: 1;
          transform: scale(1)
     }
}
2020/03/13 17:31:19

不需要JavaScript,也不需要极大的最大高度。相反,请max-height在您的文本元素上进行设置,并使用字体相对单位,例如remem这样,您可以将最大高度设置为大于容器的高度,同时避免菜单关闭时的延迟或“弹出”:

的HTML

<nav>
  <input type="checkbox" />
  <ul>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
  </ul>
</nav>

的CSS

nav input + ul li { // Notice I set max-height on li, not ul
   max-height: 0;
}

nav input:checked + ul li {
   max-height: 3rem; // A little bigger to allow for text-wrapping - but not outrageous
}

在此处查看示例:http : //codepen.io/mindfullsilence/pen/DtzjE

Harry逆天Eva2020/03/13 17:31:19

在写完Guillermo的可接受答案之后,2012-04-03的CSS过渡规范更改了可见性过渡的行为,现在可以以较短的方式解决此问题,而无需使用transition-delay:

.myclass > div {
                   transition:visibility 1s, opacity 1s;
                   visibility:hidden;  opacity:0
               }
.myclass:hover > div
               {   visibility:visible; opacity:1 }

为两个过渡指定的运行时间通常应该是相同的(尽管可见性的时间稍长一点也不成问题)。

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

写下问题“显示的过渡:属性”的标题,并回应Rui Marques和josh对已接受答案的评论:

如果使用display或visible属性不相关(在此问题中可能就是这种情况),则此解决方案适用

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

display:none可以使用高度(如其他答案和注释所示),max-height或margin-top / bottom 完全删除类似于元素的过渡,另请参见 如何过渡height:0; 达到高度:自动;使用CSS?和我的博客文章Display和Height属性上CSS过渡解决方法

回应GeorgeMillo的评论:需要同时使用这两个属性和两个过渡:不透明度属性用于创建淡入和淡出动画以及可见性属性,以避免元素仍然对鼠标事件做出反应。需要对不透明性进行过渡以实现视觉效果,并需要对可见性进行过渡以延迟隐藏,直到淡出完成为止。

Davaid前端2020/03/13 17:31:19

更改overflow:hiddenoverflow: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

Gil西里斯丁2020/03/13 17:31:19

我已经多次遇到这个问题,现在简单地讲:

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

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

通过添加该类block--invisible,整个Elements将不可单击,但是其后面的所有Elements都将因为pointer-events:none所有主要浏览器(没有IE <11)都支持。

小宇宙樱2020/03/13 17:31:19

我今天遇到了这个问题,并且使用了position: fixed我正在重用模式。我不能保留它display: none,然后对其进行动画处理,因为它刚刚出现在外观上,并且z-index负值等)也做得很奇怪。

我也使用了height: 0to height: 100%,但是它只有在出现模态时才起作用。这与您使用过的left: -100%东西相同。

然后令我惊讶的是,有一个简单的答案。瞧!

首先,您的隐藏模式。注意heightis 0,并检查height过渡中声明...它有一个a 500ms比我的opacitytransition 更长请记住,这会影响向外的淡出过渡:将模态恢复为其默认状态。

#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-activebody现在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;
}

就是这样,它就像一种魅力。

小小逆天2020/03/13 17:31:19

从这些答案中的一些以及其他建议中,以下内容非常适合悬停菜单(特别是我将其与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也可以使用因为s height:auto不允许使用transition的悬浮值max-height需要大于height菜单的可能。

阿飞番长2020/03/13 17:31:19

编辑:在此示例中,不显示任何内容。

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

上面发生的事情是,在不透明度逐渐消失的情况下,通过99%的动画显示被设置为阻止。最后一刻,display属性设置为none。

最重要的一点是使用animation-fill-mode保留动画结束后的最后一帧:

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

这是两个示例:https : //jsfiddle.net/qwnz9tqg/3/

Green樱2020/03/13 17:31:19

您现在可以将自定义动画添加到block属性。

@keyframes showNav {
  from {opacity: 0;}
  to {opacity: 1;}
}
.subnav-is-opened .main-nav__secondary-nav {
  display: block;
  animation: showNav 250ms ease-in-out both;
}

演示版

在此演示中,子菜单从display:none变为display:block,但仍设法消失。

古一斯丁2020/03/13 17:31:19

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!).

老丝梅樱2020/03/13 17:31:19

您需要通过其他方式隐藏元素才能使其正常工作。

我通过<div>绝对定位两个s并将隐藏的设置为来达到效果opacity: 0

如果您甚至将display属性从切换noneblock,也不会在其他元素上进行转换。

要变通解决此问题,请始终将元素设置为display: block,但可以通过调整以下任何一种方式隐藏该元素:

  1. 将设置height0
  2. 将设置opacity0
  3. 将元素放置在另一个具有的元素的框架之外overflow: hidden

可能还有更多解决方案,但是如果将元素切换为,则无法执行过渡display: none例如,您可以尝试尝试如下操作:

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

但是,这并不工作。根据我的经验,我发现这无济于事。

因此,您将始终需要保留元素display: block-但您可以通过执行以下操作来解决该问题:

div {
    transition: opacity 1s ease-out;
    opacity: 0;
    height: 0;
    overflow: hidden;
}
div.active {
    opacity: 1;
    height: auto;
}
Pro宝儿2020/03/13 17:31:19

display 不是过渡所依据的属性之一。

有关可以应用过渡的CSS属性列表,请参见Animatable CSS属性请参阅CSS值和单位模块级别4,组合值:插值,加法和累加,以了解如何进行插值。

9.1中最多列出了CSS 3 CSS中的属性(只需关闭警告弹出窗口)

我也尝试过使用高度,但是那不幸地失败了。

上次我必须这样做时,我max-height改用了这是一个可动画处理的属性(尽管有点hack,但它确实起作用了),但是请注意,对于复杂的页面或使用低端移动设备的用户而言,它可能会显得非常笨拙设备。

小卤蛋Tom2020/03/13 17:31:19

代替使用CSS中不存在的回调,我们可以使用transition-delayproperty。

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

那么,这是怎么回事?

  1. visible类被添加,既heightopacity无延迟启动动画(0毫秒),尽管height需要0ms到完整的动画(当量display: block)和opacity花费600毫秒。

  2. visible类被移除时,opacity开始动画(0毫秒延迟,400毫秒持续时间),以及高度400等待毫秒和仅然后立即(0毫秒)恢复初始值(相当于display: none在动画回调)。

请注意,这种方法比使用的方法更好visibility在这种情况下,该元素仍然占据页面上的空间,并且并不总是适合。

有关更多示例,请参阅本文

逆天樱2020/03/13 17:31:19

您可以串联两个或多个过渡,visibility这是这次方便的事情。

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>

(不要忘记transition属性的供应商前缀。)

更多的细节在这篇文章