显示屏上的转换:属性

Ric*_*ape 1322 css css-transitions

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

目前,似乎CSS3过渡不适用于"display"属性,即你不能做任何类型的过渡display: nonedisplay: block(或任意组合).

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

我知道你可以在visibility:属性上使用转换,但我想不出有效利用它的方法.

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

我也知道使用JavaScript实现这一点是微不足道的,但是我想挑战自己只使用CSS而且我认为我有点短.

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

Gui*_*rmo 1248

您可以连接两个或更多转换,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;
}
Run Code Online (Sandbox Code Playgroud)
<div>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</div>
Run Code Online (Sandbox Code Playgroud)

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

更多细节在本文中

  • 这很好,但问题是"隐藏可见性"元素仍然占据空间,而"display none"则不占用空间. (691认同)
  • 我可能遗漏了一些东西,但你为什么要改变能见度和不透明度呢?不会将不透明度设置为0隐藏元素 - 为什么还需要将可见性设置为隐藏? (40认同)
  • 是的,这个问题是它背后的任何东西都会重叠,即使它不可见.我发现使用高度:0是一个更好的解决方案 (20认同)
  • @GeorgeMillo如果你只设置了不透明度,那么该元素实际上仍然在页面渲染上(例如你无法点击思考). (17认同)
  • 这个答案似乎比其他答案少,并且实现了我们对display的期望:none/block; 谢谢.节省了我很多时间. (10认同)
  • 这不应该被标记为正确的答案.它没有处理显示属性,正如Rui所说,元素仍然占用空间,这使得它在许多情况下都不切实际. (9认同)
  • @ChristopherCliff和大家,我刚刚发现了一种简单的方法,可以在**鼠标悬停和鼠标输出上平滑过渡:使用相同的**持续时间和时间函数转换"可见性"作为"不透明度" :`过渡:可见性0.5s线性,不透明度0.5s线性;`.这是因为插入了`visibility`过渡的方式:中间值设置为`visible`.有关详细信息,请参阅:https://developer.mozilla.org/en-US/docs/Web/CSS/visibility#Interpolation和http://www.taccgl.org/blog/css-transition-visibility.html# Appearance_CSS_Visibility. (9认同)
  • @RuiMarques你可以让隐藏元素也有一个`position:absolute;`然后在悬停时你可以给它一个很好的ol''position:relative;`.然后元素在隐藏时不会占用空间,但在相对时会填充.我以为我会说些什么以供将来参考. (5认同)
  • "show"动画在`:hover`上很流畅.当`:hover`被删除时,元素被隐藏而没有转换(在0.5s延迟之后).是否有一个技巧可以在两个方向上顺利实现这种动画效果?此外,该链接似乎已死亡. (4认同)
  • 正如Rui所说,它仍然占据了空间,例如处理css下拉变得更加复杂,因为有时候它们的高度非常大并超过了主要内容容器的高度,所以页脚会有空的空间. (4认同)
  • 这里不需要@ MatthewT.Baker不透明度的供应商前缀,因为没有浏览器支持css转换但不支持opacity属性.因此,只需隐藏元素而不进行转换,它就会优雅地降级. (4认同)
  • 请注意,如果您关心可访问性(您可能会这样做),那么这个答案实际上是完全错误的:不使用“display:none”意味着页面上的每个可聚焦/制表符索引元素_仍然存在_,并且您的用户现在将盲选那些元素是完全看不见的。虽然这似乎有效,但实际上对于相当多的网络用户来说,情况变得更糟。相反,您需要一个两步过程,display:none-&gt;block 和_then_淡出不透明度,反之,淡出不透明度,然后display:block-&gt;none。 (4认同)
  • 很好的答案,但我只是注意到,当时间设置为"0"时,转换不起作用,它必须设置为"0".这对我来说很糟糕,因为据我所知,零不应该有任何单位. (3认同)
  • @scavaJripter在```position:relative```和```position:absolute```之间交换的问题是```position```是不可动画的.如果是的话,你是对的,我们将无家可归.但是看到它不可动画,与切换```display:none```相比,我们的位置并没有那么好.如果我们尝试您的解决方案,我们仍然会获得非常基本的输出(至少在一个方向上).http://jsfiddle.net/eu4jztzr/9/ (2认同)
  • 你还可以为`visibility`添加一个延迟值,如:`transition:opacity 1s ease,visibility 0s ease 1s;`并在hover上移除它`transition:opacity 1s ease 0s,visibility 0s easy 0s;`for in-out动画. (2认同)

Jim*_*ers 759

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

我通过<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;
}
Run Code Online (Sandbox Code Playgroud)

但是,这并不工作.根据我的经验,我发现这无所事事.

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

div {
    transition: opacity 1s ease-out;
    opacity: 0;
    height: 0;
    overflow: hidden;
}
div.active {
    opacity: 1;
    height: auto;
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢吉姆的全面答复.如果显示:属性完全改变,那么你的所有转换都不起作用,这是完全正确的事实.这是一种耻辱 - 我想知道背后的原因是什么.在旁注中,在我在原始问题中发布的同一链接上,您可以看到我在哪里.我在Chrome [5.0.375.125]中遇到的唯一(小)问题是,当页面加载时,您可以看到菜单在页面上加载元素时快速消失.Firefox 4.0b2和Safari 5.0绝对没问题......我错过了什么错误? (28认同)
  • 我同意这是正确的,并将为此做出贡献; 面向未来的旅行者.我在Chrome中找到了一个可行的解决方案,但我发现它在iPhone 4上失败了:`visibility:hidden; 不透明度:0; -webkit-transition:所有.2s轻松进出;`这不仅没有正确转换,而且目标元素永远不会出现.QA会让你,我和你的妈妈失望. (7认同)
  • 你刚刚赢得了投票,因为'溢出:隐藏'非常感谢你! (7认同)
  • 如果将隐藏状态设置为“ height:0;”,并且不进行过渡,则过渡将不起作用。我试图这样做只是为了过渡不透明度。我必须删除“高度:0;”。 (2认同)
  • 我实现了这个,然后它不起作用,然后我意识到你所说的**不会**起作用。这个答案假设不仅仅是快速阅读重要的部分......:) (2认同)

Sal*_*bas 260

在本文发表时,如果您尝试更改display属性,所有主流浏览器都会禁用CSS过渡,但CSS动画仍然可以正常工作,因此我们可以将它们用作解决方法.

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

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

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}
@keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}
Run Code Online (Sandbox Code Playgroud)

然后将fadeIn动画应用于父hover上的子项: - (当然设置display: block)

.parent:hover .child {
    display: block;
    -webkit-animation: fadeIn 1s;
    animation: fadeIn 1s;
}
Run Code Online (Sandbox Code Playgroud)

更新2019 - 也支持淡出的方法:

(有些JS需要)

// We need to keep track of faded in elements so we can apply fade out later in CSS
document.addEventListener('animationstart', function (e) {
  if (e.animationName === 'fade-in') {
      e.target.classList.add('did-fade-in');
  }
});

document.addEventListener('animationend', function (e) {
  if (e.animationName === 'fade-out') {
      e.target.classList.remove('did-fade-in');
   }
});
Run Code Online (Sandbox Code Playgroud)
div {
    border: 5px solid;
    padding: 10px;
}

div:hover {
    border-color: red;
}

.parent .child {
  display: none;
}

.parent:hover .child {
  display: block;
  animation: fade-in 1s;
}

.parent:not(:hover) .child.did-fade-in {
  display: block;
  animation: fade-out 1s;
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fade-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
Run Code Online (Sandbox Code Playgroud)
<div class="parent">
    Parent
    <div class="child">
        Child
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,非常有用.但是如何淡出它呢? (41认同)
  • 最好的答案,过渡不可能,但动画是的. (7认同)
  • 反向动画怎么样,那就是元素应该慢慢消失的时候? (6认同)
  • 谢谢你.上面提到的`height:0`技巧(用于过渡)似乎不起作用,因为在淡出过渡时高度设置为0,但这个技巧似乎工作正常. (3认同)
  • 这个答案的第一段不太合理。浏览器不会在您使用 `display` 属性时立即禁用所有过渡 - 真的没有理由这样做。即使他们*做了*,那为什么动画会起作用呢?你也不能在 CSS 动画中使用 `display` 属性。 (2认同)

小智 69

我怀疑如果"显示"发生变化,过渡被禁用的原因是因为显示实际上是什么.它并没有改变任何东西,可以令人信服地平滑的动态.

"display:none;"和"visibility:hidden;"是两个完全不同的东西.两者都具有使元素不可见的效果,但是"visibility:hidden;"它仍然在布局中呈现,但只是不明显.隐藏元素仍占用空间,仍然以内联或块或块内联或表格或"display"元素告诉它呈现为的方式呈现,并相应占用空间.其他元素不会自动移动以占据该空间.隐藏元素只是不将其实际像素渲染到输出.

另一方面,"display:none"实际上阻止了元素的完全渲染.它不占用任何布局空间.其他元素将占据该元素占用的部分或全部空间,现在可以调整占据该空间,就好像该元素根本不存在一样.

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

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

  • 我不同意.它可以完全有道理.如果显示:无显示:在转换开始时立即发生阻塞,那将是很好的.而对于过渡回来,如果它从显示:阻止到显示:在转换结束时没有,那将是完美的. (8认同)
  • 与上述解决方案一样,对于为什么转换不适用于显示属性,获得合理的解释是非常令人满意的. (5认同)

rob*_*cat 50

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

有关可应用转换的CSS属性列表,请参阅https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties.有关如何插值的信息,请参阅https://drafts.c​​sswg.org/css-values-4/#combining-values.

最高CSS3列于https://www.w3.org/TR/2017/WD-css-transitions-1-20171130/#animatable-css(只需关闭警告弹出窗口)


Web*_*ars 39

我们可以使用transition-delay属性来代替CSS中不存在的回调.

#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;
}
Run Code Online (Sandbox Code Playgroud)

那么,这里发生了什么?

  1. visible类添加,两者heightopacity没有延迟启动动画(0毫秒),虽然height花费0毫秒即可完成动画(等效display: block),并opacity需要600毫秒.

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

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

有关更多示例,请参阅此文章.

  • 感到惊讶的是没有更多的赞成 - 这个聪明的解决方案在某种程度上完美无缺. (7认同)
  • 你必须设置一个高度 - 设置 `height: auto` 会使它立即消失。 (5认同)
  • 它只能与“ height:100%”一起使用,在某些情况下会破坏布局。很好的解决方案,如果那不是问题。少数双向工作之一。 (3认同)
  • 即使使用React,它也能满足我的需要.谢谢 (3认同)

Man*_*han 34

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

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

演示

在这个演示中,子菜单从更改display:nonedisplay:block仍然设置为淡入淡出.

  • 除非我遗漏了某些内容,否则"演示"链接不再显示子菜单转换. (22认同)
  • 嘿,您的演示链接遵循`developers.google.com` (3认同)

小智 32

我找到了解决这个问题的更好方法,您可以使用 CSS Animation 并制作显示项目的出色效果。

.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)
     }
}
Run Code Online (Sandbox Code Playgroud)

  • 太糟糕了,它不适用于淡出 (7认同)

fek*_*lee 21

根据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>
    
    Run Code Online (Sandbox Code Playgroud)
  • 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;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 用于测试的JavaScript:

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

请注意,如果您只是将链接设为透明而不进行设置visibility: hidden,那么它将保持可点击状态.


小智 13

我的整洁JavaScript技巧是将整个场景分成两个不同的功能!

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

  var tTimeout;
  element.addEventListener("transitionend", afterTransition, true);//firefox
  element.addEventListener("webkitTransitionEnd", afterTransition, true);//chrome
Run Code Online (Sandbox Code Playgroud)

然后,当隐藏元素时,我使用这样的东西:

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

function afterTransition(){
  element.style.display = 'none';
}
Run Code Online (Sandbox Code Playgroud)

为了重新出现元素,我正在做这样的事情:

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

function timeoutShow(){
  element.style.opacity = 1;
}
Run Code Online (Sandbox Code Playgroud)

它到目前为止有效!


Paw*_*wel 12

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

@keyframes hide {
  0% {
    display: block;
    opacity: 1;
  }
  99% {
    display: block;
  }
  100% {
    display: none;
    opacity: 0;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

.hide {
   animation: hide 1s linear;
   animation-fill-mode: forwards;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 正如你可以在这个用游标设置的小提琴中看到的那样,`display:none`,实际上从未实现过.https://jsfiddle.net/3e6sduqh/ (3认同)

小智 10

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

我也使用height: 0height: 100%,但只有当出现模式工作.这与您使用的left: -100%东西相同.

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

首先,你隐藏的模态.注意heightis 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;
}
Run Code Online (Sandbox Code Playgroud)

第二,你的可见模态.说你设定.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;
}
Run Code Online (Sandbox Code Playgroud)

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


Edy*_*dyn 8

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

如果您指定两个值height,也可以使用它代替,max-height因为s height:auto不允许transition.悬停值可能max-height需要大于height菜单的悬停值.


小智 8

在这种情况下应用过渡而不使用关键帧的另一种方法是将元素的宽度设置为零,然后在悬停时取消设置

.className{
  visibility:hidden;
  opacity: 0;
  transition: .2s;
  width:0;
}

.className:hover{
  visibility:visible;
  margin-right: .5rem;
  opacity: 1;
  width:unset;
}
Run Code Online (Sandbox Code Playgroud)


Rom*_*nev 7

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

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

<div class="animation"></div>
<div class="transition"></div>
Run Code Online (Sandbox Code Playgroud)
@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);
}
Run Code Online (Sandbox Code Playgroud)


Dom*_*rer 6

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

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

.block--invisible {
  pointer-events: none;
  opacity: 0;
}
Run Code Online (Sandbox Code Playgroud)

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


Lar*_*ndt 5

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

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

PS 如果您发现自己处于需要display:block同时执行这两项操作并添加“on”类的情况,请使用 setTimeout 推迟后者。否则,浏览器只会将这两件事视为同时发生并禁用转换。


小智 5

更改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;
}
Run Code Online (Sandbox Code Playgroud)

visible更好,因为overflow:hidden行为完全像一个display:none.


min*_*nce 5

不需要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>
Run Code Online (Sandbox Code Playgroud)

的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
}
Run Code Online (Sandbox Code Playgroud)

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


小智 5

在Guillermo接受的答案被写入后,2012年4月3日的CSS转换规范改变了可见性转换的行为,现在可以在不使用转换延迟的情况下以更短的方式解决此问题:

.myclass > div {
                   transition:visibility 1s, opacity 1s;
                   visibility:hidden;  opacity:0
               }
.myclass:hover > div
               {   visibility:visible; opacity:1 }
Run Code Online (Sandbox Code Playgroud)

为两个转换指定的运行时间通常应该相同(尽管稍长的可见性时间不是问题).有关正在运行的版本,请参阅我的博客 http://www.taccgl.org/blog/css-transition-visibility.html#visibility-opacity.

Wrt题为"转换显示:属性"的问题,并回应Rui Marques和josh对已接受答案的评论:此解决方案适用于如果使用显示或可见性属性无关紧要的情况(因为它可能是这个问题的情况).它不会完全删除元素display:none,只是让它不可见但它仍然停留在文档流中并影响以下元素的位置.完全删除类似于display的元素的过渡:none可以使用height(如其他答案和注释所示),max-height或margin-top/bottom来完成,但也可以看到 如何转换高度:0; 高度:自动; 用CSS? 和我的博客http://www.taccgl.org/blog/css_transition_display.html.

回应GeorgeMillo的评论:需要属性和两个转换:不透明度属性用于创建淡入和淡出动画以及可见性属性,以避免元素仍对鼠标事件做出反应.视觉效果的不透明度和延迟隐藏的可见性需要转换,直到淡出结束.


Chr*_*ini 5

您可以让它以您期望的自然方式工作 - 使用显示 - 但您必须限制浏览器才能使其工作,使用 Javascript 或其他人建议的一种奇特的技巧,将一个标签放在另一个标签中。我不关心内部标签,因为它使 CSS 和尺寸进一步复杂化,所以这里是 Javascript 解决方案:

\n

https://jsfiddle.net/b9chris/hweeyecu4/17/

\n

从一个像这样的盒子开始:

\n
<div id="box" class="hidden">Lorem</div>\n
Run Code Online (Sandbox Code Playgroud)\n

一个隐藏的盒子。

\n
div.hidden {\n    display: none;\n}\n#box {\n    transition: opacity 1s;\n}\n    \n
Run Code Online (Sandbox Code Playgroud)\n

我们将使用相关问答中发现的技巧,检查 offsetHeight 以立即限制浏览器:

\n

/sf/answers/1160306801/

\n

首先,一个库将上述技巧形式化:

\n
$.fn.noTrnsn = function () {\n    return this.each(function (i, tag) {\n        tag.style.transition = \'none\';\n    });\n};\n$.fn.resumeTrnsn = function () {\n    return this.each(function (i, tag) {\n        tag.offsetHeight;    \n        tag.style.transition = null;\n    });\n};\n
Run Code Online (Sandbox Code Playgroud)\n

接下来,我们将使用它来显示一个框,并将其淡入:

\n
$(\'#button\').on(\'click\', function() {\n    var tag = $(\'#box\');\n    if (tag.hasClass(\'hidden\'))\n        tag.noTrnsn().removeClass(\'hidden\')\n        .css({ opacity: 0 })\n        .resumeTrnsn().css({ opacity: 1 });\n    else\n        tag.css({ opacity: 0 });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

这会使框淡入和淡出。因此,.noTrnsn()关闭转换,然后我们删除该类hidden,该类display将从none默认值block. 然后我们将不透明度设置为 0 以准备淡入。现在我们已经做好了准备,我们使用 重新打开过渡.resumeTrnsn()。最后,将不透明度设置为 1 来开始过渡。

\n

如果没有库,显示的更改和不透明度的更改都会给我们带来不希望的结果。如果我们只是删除库调用,我们根本不会得到任何转换。

\n

请注意,上面不会在淡出动画结束时再次将显示设置为无。不过我们还可以变得更漂亮。让我们用一个淡入并从 0 开始增加高度的对象来实现这一点。

\n

想要!

\n

https://jsfiddle.net/b9chris/hweeyecu4/22/

\n
#box {\n    transition: height 1s, opacity 1s;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我们现在正在转换高度和不透明度。请注意,我们没有设置高度,这意味着它是默认高度auto。按照惯例,这是无法转换的 - 从自动移动到像素值(如 0)将不会导致转换。我们将使用库和另一种库方法来解决这个问题:

\n
$.fn.wait = function (time, fn) {\n    if (time)\n        this.delay(time);\n    if (!fn)\n        return this;\n\n    var _this = this;\n    return this.queue(function (n) {\n        fn.call(_this);\n        n();\n    });\n};\n
Run Code Online (Sandbox Code Playgroud)\n

这是一种方便的方法,可以让我们参与 jQuery 现有的 fx/animation 队列,而不需要任何现在被排除在 jQuery 3.x 中的动画框架。我不会解释 jQuery 是如何工作的,但足以说明,jQuery 提供的管道.queue().stop()管道帮助我们防止动画相互干扰。

\n

让我们制作向下滑动效果的动画。

\n
$(\'#button\').on(\'click\', function() {\n    var tag = $(\'#box\');\n    if (tag.hasClass(\'hidden\')) {\n        // Open it\n        // Measure it\n        tag.stop().noTrnsn().removeClass(\'hidden\').css({\n            opacity: 0, height: \'auto\'\n        });\n        var h = tag.height();\n        tag.css({ height: 0 }).resumeTrnsn()\n        // Animate it\n        .css({ opacity: 1, height: h })\n        .wait(1000, function() {\n            tag.css({ height: \'auto\' });\n        });\n    } else {\n        // Close it\n        // Measure it\n        var h = tag.noTrnsn().height();\n        tag.stop().css({ height: h })\n        .resumeTrnsn()\n        // Animate it\n        .css({ opacity: 0, height: 0 })\n        .wait(1000, function() {\n            tag.addClass(\'hidden\');\n        });\n    }\n});\n
Run Code Online (Sandbox Code Playgroud)\n

这段代码首先通过检查#box它的类来检查它当前是否隐藏。但它wait()通过在滑出/淡入动画末尾添加类来使用库调用完成更多工作,hidden您希望找到它是否实际上是隐藏的 - 这是上面更简单的示例无法做到的。这恰好也会反复显示/隐藏元素,这是前面示例中的一个错误,因为隐藏的类从未恢复。

\n

您还可以看到 CSS 和类更改被调用,通常.noTrnsn()为动画设置舞台,包括进行测量,例如在调用之前测量最终高度而不#box向用户显示.resumeTrnsn(),并根据完整设置对其进行动画处理达到其目标 CSS 值的阶段。

\n

旧答案

\n

https://jsfiddle.net/b9chris/hweeyecu4/1/

\n

您可以通过以下方式使其在单击时转换:

\n
function toggleTransition() {\n  var el = $("div.box1");\n\n  if (el.length) {\n    el[0].className = "box";\n    el.stop().css({maxWidth: 10000}).animate({maxWidth: 10001}, 2000, function() {\n        el[0].className = "box hidden";\n    });\n  } else {\n    el = $("div.box");\n    el[0].className = "box";\n    el.stop().css({maxWidth: 10001}).animate({maxWidth: 10000}, 50, function() {\n        el[0].className = "box box1";\n    });\n  }\n\n  return el;\n}\n\nsomeTag.click(toggleTransition);\n
Run Code Online (Sandbox Code Playgroud)\n

CSS 就是你猜的那样:

\n
.hidden {\n    display: none;\n}\n.box {\n    width: 100px;\n    height: 100px;\n    background-color: blue;\n    color: yellow;\n    font-size: 18px;\n    left: 20px;\n    top: 20px;\n    position: absolute;\n    -webkit-transform-origin: 0 50%;\n    transform-origin: 0 50%;\n    -webkit-transform: scale(.2);\n    transform: scale(.2);\n    -webkit-transition: transform 2s;\n    transition: transform 2s;\n}\n.box1{\n    -webkit-transform: scale(1);\n    transform: scale(1);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

关键是限制显示属性。通过删除隐藏类,然后等待 50\xc2\xa0ms,然后通过添加的类开始转换,我们让它出现,然后像我们想要的那样展开,而不是只是在没有任何动画的情况下在屏幕上闪烁。反之亦然,类似的情况也会发生,只不过我们要等到动画结束后再应用隐藏。

\n

注意:我.animate(maxWidth)在这里滥用是为了避免setTimeout竞争条件。setTimeout当您或其他人在不知情的情况下获取代码时,很快就会引入隐藏的错误。.animate()很容易被杀死.stop()。我只是用它在标准 fx 队列上放置 50\xc2\xa0ms 或 2000\xc2\xa0ms 延迟,在此基础上构建的其他编码人员很容易找到/解决。

\n


Dam*_*ica 5

通过opacityposition absolute(隐藏时不占用空间)结合,我终于为我找到了解决方案。

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

.parent:hover .toggle {
  opacity: 1;
  position: static;
}
Run Code Online (Sandbox Code Playgroud)


Vel*_*vic 5

它就像以下一样简单:)

@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;
Run Code Online (Sandbox Code Playgroud)

让它消失,然后让它消失height 0;。还要确保使用 forwards 以使其保持最终状态。


Nat*_*lie 5

CSS 动画淡化它:

.item {
     display: none;
}

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

@keyframes fadeIn {
     from {
          opacity: 0;
     }

     to {
          opacity: 1;
     }
}
Run Code Online (Sandbox Code Playgroud)