题 显示屏上的转换:属性


我目前正在设计一种CSS'mega dropdown'菜单 - 基本上只是一个普通的CSS下拉菜单,但包含不同类型的内容。

在这一刻, 似乎CSS3 Transitions不适用于'display'属性,即你不能做任何过渡 display: none 至 display: block (或任何组合)。

当有人将鼠标悬停在其中一个顶级菜单项上时,是否有人会想到上述示例中的第二层菜单的方式为“淡入”?

我知道你可以使用转换 visibility: 财产,但我想不出有效利用这种方法的方法。

我也试过使用身高,但这只是失败了。

我也意识到使用JavaScript实现这一目标是微不足道的,但我想挑战自己只使用CSS而且我认为我有点短暂。

所有和任何建议最受欢迎。


1074
2017-07-25 22:52


起源


如果将CSS应用于不透明度属性而不是显示,那么CSS过渡是否有效? - Paul D. Waite
位置:绝对;能见度:隐藏;与display:none相同; - Jawad
@Jawad:只有你添加类似的东西 z-index:0 同样。 - DanMan
@Jawad:建议永远不要使用 visibility: hidden 除非你 想 屏幕阅读器阅读它(而典型的浏览器不会)。它只定义了 能见度 元素(如说 opacity: 0),它仍然是可选择的,可点击的,以及以前的任何东西;它只是不可见。 - Forest Ka
不支持 pointer-events 在IE 8,9,10中,所以它并不总是好的 - Steven Pribilinskiy


答案:


您可以连接两个或更多转换,以及 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 属性)

更多细节在 本文


1026
2017-08-04 14:58



visibility 对我来说工作得很好 - 最后这个属性很好用 :) - Kobi
是的,这个问题是它背后的任何东西都会重叠,即使它不可见。我发现使用高度:0是一个更好的解决方案 - Josh Bedo
这很好,但问题是“隐藏可见性”元素仍然占据空间,而“display none”则不占用空间。 - Rui Marques
我可能错过了什么,但为什么你改变了可见性和不透明度?不会将不透明度设置为0隐藏元素 - 为什么还需要将可见性设置为隐藏? - GMA
@GeorgeMillo如果只设置不透明度,则该元素实际上仍然在页面渲染上(例如,您无法单击思考)。 - Grsmto


您需要通过其他方式隐藏元素才能使其生效。

我通过定位两者来完成效果 <div>绝对是设置隐藏的 opacity: 0

如果你甚至切换了 display 财产来自 none 至 block,您不会发生其他元素的转换。

要解决此问题,请始终允许元素 display: block,但通过调整以下任何方式隐藏元素:

  1. 设置 height 至 0
  2. 设置 opacity 至 0
  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;
}

660
2017-07-26 04:20



感谢吉姆提供了彻底的答复。如果显示:属性完全改变,那么你的所有转换都不起作用,你是完全正确的。这是一种耻辱 - 我想知道背后的原因是什么。在旁注中,在我在原始问题中发布的同一链接上,您可以看到我在哪里。我在Chrome [5.0.375.125]中遇到的唯一(小)问题是,当页面加载时,您可以看到菜单快速消失,因为元素已加载到页面上。 Firefox 4.0b2和Safari 5.0绝对没问题......我错过了什么错误? - RichardTape
我同意这是正确的,并将为此做出贡献;面向未来的旅行者。我在Chrome中找到了一个可行的解决方案,但我发现它在iPhone 4上失败了: visibility:hidden; opacity:0; -webkit-transition: all .2s ease-in-out; 这不仅没有正确转换,而且目标元素永远不会出现。 QA会让你,我和你的妈妈失望。 - SimplGy
您实际上也可以转换可见性属性..只是说 - Cu7l4ss
如果将隐藏状态设置为 height: 0; 并且不要过渡它,过渡将不起作用。我尝试过这只是试图过渡不透明度。我不得不删除 height: 0; - chovy
你刚刚赢得了投票,因为 overflow: hidden 万分感谢! - thiagoh


在本文发布时,如果您尝试更改,则所有主流浏览器都会禁用CSS转换 display 属性,但CSS动画仍然可以正常工作,所以我们可以使用它们作为解决方法。

示例代码: -    (您可以相应地将它应用到您的菜单中) 演示

将以下CSS添加到样式表: -

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

然后申请 fadeIn 父母悬停时对孩子的动画: - (当然还有 display: block

.parent:hover .child {
    display: block;
    -webkit-animation: fadeIn 1s;
    animation: fadeIn 1s;
}

203
2018-02-17 19:25



谢谢你。该 height: 0 上面提到的技巧(用于转换)似乎不起作用,因为在淡出过渡时高度设置为0,但这个技巧似乎工作正常。 - Elliot Winkler
谢谢,非常有用。但是如何淡出呢? - Illiou
这个答案的第一段没有多大意义。浏览器不会在您使用时立即禁用所有转换 display 财产 - 没有理由。即使他们 没有,为什么动画会起作用呢?你不能使用 display CSS动画中的属性。 - BoltClock♦
最好的答案,过渡不可能,但动画是的。 - Mikel
反向动画怎么样,那就是元素应该慢慢消失的时候? - Green


我怀疑了 原因 如果更改“显示”是因为实际显示的是什么,则禁用转换。确实如此  改变任何可以想象得流畅动画的东西。

“display:none;”和“visibility:hidden;”是两个 完全 不同的东西。两者都具有使元素不可见的效果,但是“visibility:hidden;”它仍然在布局中呈现,但不是 明显地 所以。隐藏元素仍然占用空间,并且仍然以内联或块或块内联或表格或“display”元素告诉它呈现为的任何内容呈现,并相应地占用空间。其他元素呢  自动移动占据那个空间。隐藏元素不会将其实际像素呈现给输出。

另一方面,“显示:无” 防止 渲染中的元素 完全。它没有占用 任何 布局空间。其他元素会占用这个元素占据的部分或全部空间,现在可以调整占据该空间,就好像元素一样 根本不存在

“显示”不仅仅是另一种视觉属性。它建立元素的整个渲染模式,例如它是块,内联,内联块,表,表行,表格单元,列表项还是其他任何东西!每个都有非常不同的布局分支,并且没有合理的方式来动画或平滑过渡它们(试图想象从“块”到“内联”的平滑过渡,或反之亦然,例如!)。

这就是为什么在显示改变时禁用转换的原因(即使改变是来自或来自“无” - “无”不仅仅是不可见,它是它自己的元素渲染模式,这意味着根本没有渲染!),


54
2018-06-15 18:55



这是对的。这并不是很明显,但是一旦你考虑到这一点,你就不需要花很长时间才能意识到转变它 display 财产不可能 工作。 - BoltClock♦
与上述解决方案一样,对于为什么转换不适用于显示属性,获得合理的解释是非常令人满意的。 - kqr
我不同意。它可以完全有道理。如果显示:无显示:在转换开始时立即发生阻塞,这将是很好的。而对于过渡回来,如果它从显示:阻止到显示:在转换结束时没有,那将是完美的。 - Curtis Yallop
如果你无法想象从点到矩形的动画是什么样的,你就会遇到问题。从占用空间到占据矩形空间的过渡非常明显,就像每次用鼠标拖动矩形一样,每次应用都会这样做。由于这次失败,有太多涉及最大高度和负边距的黑客,这是非常荒谬的。唯一有效的方法是缓存“真实”高度,然后使用JavaScript将动画从零动画到缓存值。伤心。 - Triynko
Tryniko:display:none不会将元素的大小更改为0 x 0的矩形 - 它会将其从DOM中删除。您可以通过将width和height属性设置为零来设置从矩形到点的动画,然后其他元素将围绕它流动,就像它具有'display:none',但其'display'属性将保持为'block';该元素仍在DOM中。在display:block和display之间动画的概念:none是荒谬的:没有中间状态。一个元素或者存在于DOM中,或者它不存在,无论它有多么小或不可见。 - Steve Thorpe


display 不是转换所依据的属性之一。

看到 http://www.w3.org/TR/css3-transitions/#animatable-properties- 对于可以应用过渡的属性列表。


41
2017-09-22 23:24





我知道这是一个非常古老的问题但是对于正在查看此线程的人来说,您现在可以向块属性添加自定义动画。

@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 并且仍然设法褪色。


28
2017-07-29 20:51



应该 myfirst 是 showNav 这里?那火狐呢?不幸的是,我在你提到的演示页面上找不到相关的东西。 - Sebastian vom Meer
谢谢@SebastianG。我做了更正并在上面添加了更多信息。 - Manish Pradhan
@Sebastian vom Meer:较旧的Firefox版本需要“-moz-”供应商前缀,请参阅已编辑的代码 - Herr_Schwabullek
除非我遗漏了某些内容,否则“演示”链接不再显示子菜单转换。 - Realistic
嘿,您的演示链接如下 developers.google.com - Green


根据 W3C工作草案2013年11月19日  display 不是 动画属性。幸好, visibility 是可动画的。您可以通过不透明度的过渡来链接其过渡(的jsfiddle):

  • HTML:

    <a href="http://example.com" id="foo">Foo</a>
    <button id="hide-button">Hide</button>
    <button id="show-button">Show</button>
    
  • CSS:

    #foo {
        transition-property: visibility, opacity;
        transition-duration: 0s, 1s;
    }
    
    #foo.hidden {
        opacity: 0;
        visibility: hidden;
        transition-property: opacity, visibility;
        transition-duration: 1s, 0s;
        transition-delay: 0s, 1s;
    }
    
  • 用于测试的JavaScript:

    var foo = document.getElementById('foo');
    
    document.getElementById('hide-button').onclick = function () {
        foo.className = 'hidden';
    };
    
    document.getElementById('show-button').onclick = function () {
        foo.className = '';
    };
    

请注意,如果您只是使链接透明,而不进行设置 visibility: hidden,然后它会保持可点击。


17
2018-02-02 14:59



我在jsfiddle示例中根本没有看到任何过渡 - Gino
@Gino我通过改变来修复它 0 至 0s。显然,在过去我用于测试的浏览器支持无单位零次。然而,无单位时间 不 的一部分 W3C候选人推荐,2016年9月29日。 - feklee
这应该更多。我发现它是最好的解决方案之一。 - Arthur Tarasov
停止回答该显示不是可动画的属性。请停止。这完全无关紧要。标准说显示器本身不能动画。它并没有说改变它应该阻止所有其他属性的动画工作。这是一种完全不同的症状。 - Szczepan Hołyszewski


我整洁的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;
}

它到目前为止有效!


12
2017-12-14 21:55



这确实有效,因为时间延迟,而不是因为javascript命令是单独的功能。在很多情况下,时间延迟似乎是一个很好的解决方案:) - davedadizzel


编辑:在此示例中未显示任何未应用。

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

上面发生的是,99%的动画显示设置为阻止,而不透明度淡出。在最后一刻,display属性设置为none。

最重要的一点是在动画结束后使用动画填充模式保留最后一帧:前进

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

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


12
2017-10-30 05:27



用这个解决方案 display: none 不起作用呢? - Bart Calixto
应该是'动画填充模式:前锋'而不是'前锋' - Alex
@Alex这就是“编辑”按钮的用途 - Pawel
@Alex好的。错字固定。有趣的是,我的答案甚至没有达到预期的效果,但我认为这样做是合乎逻辑的,所以我会保留它直到浏览器支持它。 - Pawel
你可以在这个小提琴中看到游标设置, display: none,从未实际实施过。 jsfiddle.net/3e6sduqh - robstarbuck


今天我遇到了这个问题 position: fixed 我正在重用的模态。我无法保留它 display: none 然后动画它,因为它刚刚跳入外观,并且 z-index (负值等)也做了奇怪的事情。

我也在用 height: 0 至 height: 100%,但它只在模态出现时才有效。这与您使用的相同 left: -100% 或者其他的东西。

然后让我感到有一个简单的答案。瞧瞧:

第一, 你隐藏的模态。请注意 height 是 0,并查看 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。现在 height 是 100%,我的过渡也发生了变化。我想要 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;
}

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


9
2018-04-19 18:49



提升您对齐供应商前缀属性的风格 - George Green


从其中一些答案和其他地方的一些建议中获取,以下内容适用于悬停菜单(我将其与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;
}

你也可以使用 height 代替 max-height 如果你指定了这两个值 height:auto 是不允许的 transition秒。悬停值 max-height 需要大于 height 菜单可能是。


8
2017-10-23 15:57



这是一个很好的技巧,但有一个缺点。过渡时间取决于高度。如果有多个菜单具有可变高度,那些高度接近最大高度的元素将会很好地生成动画。然而,较短的动画会动画太快,给人一种不一致的体验。 - user