ChatGPT解决这个技术问题 Extra ChatGPT

CSS display 属性上的转换

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

目前,CSS 3 转换似乎不适用于“display”属性,也就是说,您不能执行从 display: nonedisplay: block 的任何类型的转换(或任意组合)。

当有人将鼠标悬停在顶级菜单项之一上时,是否有办法让上例中的二级菜单“淡入”?

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

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

我也知道使用 JavaScript 实现这一点很简单,但我想挑战自己只使用 CSS,我想我有点短。

位置:绝对;可见性:隐藏;与显示相同:无;
@Jawad:仅当您还添加类似 z-index:0 的内容时。
@Jawad:建议不要使用 visibility: hidden,除非您想要 屏幕阅读器阅读它(而典型的浏览器不会)。它只定义了元素的可见性(比如说opacity: 0),并且它仍然是可选择的、可点击的,以及它过去的样子;它只是不可见。
在 IE 8,9,10 中不支持 pointer-events,所以它并不总是好的
您需要显示:无,否则您将绊倒触发器外的隐藏对象,并且它会意外显示...我只是说:)

P
Peter Mortensen

您可以连接两个或更多转换,这次 visibility 会派上用场。

div {边框:1px实心#eee; } div > ul { 可见性:隐藏;不透明度:0;过渡:可见性 0s,不透明度 0.5s 线性; } div:悬停 > ul { 可见性:可见;不透明度:1; }

  • 项目 1
  • 项目 2
  • 项目 3

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

this article 中有更多详细信息。


是的,这个问题是它背后的任何东西都会重叠,即使它不可见。我发现使用 height:0 是一个更好的解决方案
这很好,但问题是“可见性隐藏”元素仍然占用空间,而“不显示”则不会。
我可能遗漏了一些东西,但你为什么要同时改变可见性和不透明度?不会将不透明度设置为 0 隐藏元素 - 为什么还需要将可见性设置为隐藏?
@GeorgeMillo 如果您仅设置不透明度,则该元素实际上仍在页面渲染中(例如,您不能单击思想)。
这不应被标记为正确答案。它不处理 display 属性,正如 Rui 所说,该元素仍然占用空间,使其在许多情况下不切实际。
P
Peter Mortensen

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

我通过绝对定位两个 <div> 并将隐藏的一个设置为 opacity: 0 来实现效果。

即使您将 display 属性从 none 切换到 block,其他元素上的转换也不会发生。

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

将高度设置为 0。将不透明度设置为 0。将元素放置在另一个具有溢出的元素的框架之外:隐藏。

可能有更多解决方案,但如果您将元素切换到 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;
}

感谢吉姆的彻底回答。您绝对正确,如果 display: 属性发生变化,那么您的所有转换都将不起作用。真可惜——我想知道这背后的原因是什么。在旁注中,在我在原始问题中发布的同一链接上,您可以看到我在哪里。我遇到的唯一(小)问题是在 Chrome [5.0.375.125] 中页面加载时,您可以看到菜单在页面上加载元素时迅速消失。 Firefox 4.0b2 和 Safari 5.0 绝对没问题...错误或我错过了什么?
我实现了这个,然后它不起作用,然后我意识到你所说的这不起作用。这个答案假设不仅仅是快速阅读重要的部分...... :)
P
Peter Mortensen

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

示例代码(您可以将其应用到您的菜单中)Demo

将以下 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;
}

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

(需要一些 JavaScript 代码)

// 我们需要跟踪淡入元素,以便稍后在 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'); } }); div { 边框:5px 实心;填充:10px; } div:悬停 { 边框颜色:红色; } .parent .child { 显示:无; } .parent:hover .child { 显示:块;动画:淡入1s; } .parent:not(:hover) .child.did-fade-in { display: block;动画:淡出1s; } @keyframes 淡入 { from { opacity: 0; } 到 { 不透明度:1; } } @keyframes 淡出 { from { opacity: 1; } 到 { 不透明度:0; } }


谢谢你。上面提到的 height: 0 技巧(用于过渡)似乎不起作用,因为在淡出过渡时高度设置为 0,但这个技巧似乎工作得很好。
谢谢,很有用。但是如何淡出呢?
太棒了,但是当我在动画运行时悬停 DIV 时,它会闪烁(将不透明度更改为较低的状态)......有什么想法吗?
这个答案的第一段不太有意义。浏览器不会在您使用 display 属性的那一刻直接禁用所有转换 - 实际上没有理由这样做。即使他们确实,为什么动画会起作用呢?您也不能在 CSS 动画中使用 display 属性。
是的,“改变”——我不知道为什么我在那里说“使用”。我的观点是您不能转换 动画 display,但这不会阻止所有其他属性的动画,只要您不转换 none .
Y
YektaDev

我们可以使用 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;
}

那么,这里发生了什么?

添加可见类后,height 和 opacity 都会立即开始动画(0 ms),尽管 height 需要 0 ms 才能完成动画(相当于 display: block)和 opacity 需要 600 ms。移除可见类后, opacity 开始动画(0 毫秒延迟,400 毫秒持续时间),高度等待 400 毫秒,然后才立即(0 毫秒)恢复初始值(相当于动画回调中的 display: none)。

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

有关更多示例,请参阅 this article


它仅适用于在某些情况下会破坏布局的 height:100%。很好的解决方案,如果这不是问题的话。为数不多的双向工作之一。
您必须设置高度 - 设置 height: auto 使其立即消失。
A
Adriano

我怀疑如果 display 更改,过渡被禁用的原因是因为显示实际做了什么。它确实不会改变任何可以想象的平滑动画的东西。

display: none;visibility: hidden; 是两个完全 不同的东西。
两者都具有使元素不可见的效果,但使用 visibility: hidden; 它仍然在布局中呈现,但不是 < em>可见 所以。
隐藏的元素仍然占用空间,并且仍然内联或作为块或块内联或表格或任何 display 元素告诉它呈现为,并采用相应地增加空间。
其他元素不会自动移动以占据该空间。隐藏元素只是不会将其实际像素渲染到输出。

另一方面,display: none 实际上阻止元素完全呈现。
它不占用任何布局空间。
原本会占用该元素所占用的部分或全部空间的其他元素现在会调整以占用该空间,就好像该元素根本根本不存在一样。

display不仅仅是另一个视觉属性。
它建立了元素的整个渲染模式,例如是否是blockinlineinline-blocktabletable-row、{7 }、list-item 或其他任何东西!
它们中的每一个都有非常不同的布局分支,并且没有合理的方法来动画或平滑过渡它们(尝试想象从 blockinline 的平滑过渡或反之亦然,例如!)。

这就是为什么在显示更改时禁用过渡的原因(即使更改是来自或来自 none - none 不仅仅是不可见,它是它自己的元素渲染模式,这意味着根本不渲染!)。


这是对的。这不是很明显,但是一旦您考虑一下,您很快就会意识到转换 display 属性不可能工作
与上述解决方案一样好,对于为什么过渡不适用于显示属性得到一个合理的解释是非常令人满意的。
我不同意。这完全有道理。如果 display:none 到 display:block 在转换开始时立即发生,那就太好了。对于向后过渡,如果它在过渡结束时从 display:block 变为 display:none ,那将是完美的。
P
Peter Mortensen

display 不是转换适用的属性之一。

请参阅 Animatable CSS properties 了解可以应用过渡效果的 CSS 属性列表。请参阅 CSS Values and Units Module Level 4, Combining Values: Interpolation, Addition, and Accumulation 了解它们的插值方式。

9.1. Properties from CSS 中最多列出了 CSS 3(只需关闭警告弹出窗口)

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

上次我不得不这样做时,我改用了 max-height,它是一个动画属性(虽然它有点 hack,但它确实有效),但要注意它对于复杂页面或低用户- 终端移动设备。


c
ctf0

我找到了解决这个问题的更好方法,您可以使用 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)
     }
}

P
Peter Mortensen

您现在可以向块属性添加自定义动画。

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

Demo

在此演示中,子菜单从 display:none 变为 display:block 并且仍然可以淡出。


除非我遗漏了一些东西,否则“演示”链接不再显示子菜单转换。
f
feklee

根据 W3C Working Draft 19 November 2013 display 不是 动画属性。幸运的是,visibility 是可动画的。您可以将其转换与不透明度转换 (JSFiddle) 链接起来:

HTML:Foo

CSS:#foo { 过渡属性:可见性,不透明度;过渡持续时间:0s,1s; } #foo.hidden { 不透明度:0;可见性:隐藏;过渡属性:不透明度,可见性;过渡持续时间:1s,0s;转换延迟: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,那么它将保持可点击状态。


P
Pawel

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

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

上面发生的情况是,99% 的动画显示被设置为阻塞,而不透明度逐渐消失。在最后一刻显示属性设置为无。

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

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

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


您可以将 display:block 替换为 position:initial;top:initial; 并将 display:none 替换为 position:fixed;top:-1000vh; 并且它会起作用。 (将其移出屏幕并固定在正常流程之外与display:none基本相同。
n
nCardot

使用 CSS Animations 淡入:

.item {
     display: none;
}

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

@keyframes fadeIn {
     from {
          opacity: 0;
     }

     to {
          opacity: 1;
     }
}

S
Sasa Milenkovic

我巧妙的 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;
}

它有效,到目前为止!


h
hotmeteor

我今天遇到了这个问题,我正在重用一个 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;
}

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


P
Peter Mortensen

从其中一些答案和其他地方的一些建议中得出,以下内容非常适合悬停菜单(我将其与 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,因为 transition 不允许使用 height:automax-height 的悬停值需要大于菜单的 height 可能的值。


D
DominikAngerer

我多次遇到过这个问题,现在简单地说:

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

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

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


n
nhahtdh

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 完全一样。


P
Peter Mortensen

它就像以下一样简单:)

@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 以使其保持在最终状态。


R
Roman Grinev

我很感激所有的答案。这是我用于类似目的的内容:过渡与动画。

示例: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);
}

D
Damian Pavlica

我终于找到了一个解决方案,将 opacityposition absolute 结合起来(隐藏时不占用空间)。

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

.parent:hover .toggle {
  opacity: 1;
  position: static;
}

P
Peter Mortensen

不需要 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


P
Peter Mortensen

在编写了 Guillermo 接受的答案后,2012-04-03 的 CSS 过渡规范改变了可见性过渡的行为,现在可以在不使用过渡延迟的情况下以更短的方式解决这个问题:

.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 或 visibility 属性无关的情况(就像这个问题中的情况一样)。

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

完全移除类似于 display:none 的元素的转换可以使用 height(如其他答案和评论所示)、max-height 或 margin-top/bottom 来完成,但也请参阅 How can I transition height: 0; to height: auto; using CSS?和我的博文Workarounds for CSS Transitions on the Display and Height Properties

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


P
Peter Mortensen

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

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

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


C
Community

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

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

从一个盒子开始,如:

<div id="box" class="hidden">Lorem</div>

一个隐藏的盒子。

div.hidden {
    display: none;
}
#box {
    transition: opacity 1s;
}
    

我们将使用在相关 q/a 中找到的技巧,检查 offsetHeight 以立即限制浏览器:

https://stackoverflow.com/a/16575811/176877

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

$.fn.noTrnsn = function () {
    return this.each(function (i, tag) {
        tag.style.transition = 'none';
    });
};
$.fn.resumeTrnsn = function () {
    return this.each(function (i, tag) {
        tag.offsetHeight;    
        tag.style.transition = null;
    });
};

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

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

这会使盒子淡入淡出。因此,.noTrnsn() 关闭转换,然后我们删除 hidden 类,它将 displaynone 翻转为其默认值 block。然后我们将不透明度设置为 0 以准备淡入。现在我们已经设置好舞台,我们用 .resumeTrnsn() 重新打开过渡。最后,通过将不透明度设置为 1 来开始过渡。

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

请注意,上面没有在淡出动画结束时再次将 display 设置为 none。不过我们可以变得更漂亮。让我们用一个从 0 开始淡入并在高度上增长的东西来做。

想要!

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

#box {
    transition: height 1s, opacity 1s;
}

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

$.fn.wait = function (time, fn) {
    if (time)
        this.delay(time);
    if (!fn)
        return this;

    var _this = this;
    return this.queue(function (n) {
        fn.call(_this);
        n();
    });
};

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

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

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

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

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

旧答案

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

你可以让它在点击时转换:

function toggleTransition() {
  var el = $("div.box1");

  if (el.length) {
    el[0].className = "box";
    el.stop().css({maxWidth: 10000}).animate({maxWidth: 10001}, 2000, function() {
        el[0].className = "box hidden";
    });
  } else {
    el = $("div.box");
    el[0].className = "box";
    el.stop().css({maxWidth: 10001}).animate({maxWidth: 10000}, 50, function() {
        el[0].className = "box box1";
    });
  }

  return el;
}

someTag.click(toggleTransition);

CSS是你猜的:

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

关键是限制显示属性。通过移除隐藏的类,然后等待 50 毫秒,然后通过添加的类开始转换,我们让它出现,然后像我们想要的那样展开,而不是它只是在没有任何动画的情况下闪烁到屏幕上。类似的情况发生在另一个方面,除了我们等到动画结束后再应用隐藏。

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


A
AdibTE

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

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

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

D
Deadmano

我有一个类似的问题,我找不到答案。一些谷歌搜索后来把我带到了这里。考虑到我没有找到我希望的简单答案,我偶然发现了一个既优雅又有效的解决方案。

事实证明,visibility CSS 属性的值 collapse 通常用于表格项。但是,如果用于任何其他元素,它会有效地将它们呈现为 hidden,这与 display: hidden 几乎相同,但具有元素不占用任何空间并且您仍然可以制作动画的附加功能有问题的元素。

下面是一个简单的例子。

function toggleVisibility() { let exampleElement = document.querySelector('span'); if (exampleElement.classList.contains('visible')) { return; } exampleElement.innerHTML = '我不会占用空间!'; exampleElement.classList.toggle('hidden'); exampleElement.classList.toggle('visible'); setTimeout(() => { exampleElement.classList.toggle('visible'); exampleElement.classList.toggle('hidden'); }, 3000); } #main { 显示:弹性;弹性方向:列;宽度:300px;文本对齐:居中; } .hidden { 可见性:折叠;不透明度:0;过渡:可见性 2s,不透明度 2s 线性; } .visible { 可见性:可见;不透明度:1;过渡:可见性0.5s,不透明度0.5s线性; }

我会被推回去...


P
Peter Mortensen

该问题最简单的通用解决方案是:随意在您的 CSS 中指定 display:none,但是您必须使用 JavaScript 将其更改为 block(或其他任何内容),然后您还必须添加一个类您有问题的元素实际上使用 setTimeout() 进行了转换。就这样。

IE:

<style>
    #el {
        display: none;
        opacity: 0;
    }
    #el.auto-fade-in {
        opacity: 1;
        transition: all 1s ease-out; /* Future, future, please come sooner! */
        -webkit-transition: all 1s ease-out;
        -moz-transition: all 1s ease-out;
        -o-transition: all 1s ease-out;
    }
</style>

<div id=el>Well, well, well</div>

<script>
    var el = document.getElementById('el');
    el.style.display = 'block';
    setTimeout(function () { el.className = 'auto-fade-in' }, 0);
</script>

这是在最新的理智浏览器中测试的。显然它不应该在 Internet Explorer 9 或更早版本中工作。


这就像一个魅力,谢谢!
P
Peter Mortensen

我认为 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";

P
Peter Mortensen

这个方案兼容性很好,我还没见过:

.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 技巧(与“show-and-animate”一步兼容),但它使用组合 position: absolute; z-index: -1; pointer-events: none; 来确保隐藏容器 不占用空间并且不响应用户交互


P
Peter Mortensen

您可以使用转换事件来做到这一点,因此您为转换构建了两个 CSS 类,一个保存动画,另一个保存显示无状态。你在动画结束后切换它们?在我的情况下,如果我按下一个按钮,我可以再次显示 div,并删除这两个类。

试试下面的片段...

$(document).ready(function() { // 分配过渡事件 $("table").on("animationend webkitAnimationEnd", ".visibility_switch_off", function(event) { // 我们检查这是否是同一个动画we want if (event.originalEvent.animationName == "col_hide_anim") { // 在动画之后,我们分配这个基本上隐藏元素的新类。 $(this).addClass("animation-helper-display-none"); } }); $("button").click(function(event) { $("table tr .hide-col").toggleClass(function() { // 我们以切换方式切换动画类... // 我们知道在动画结束后, // 会有一个额外的动画帮助器显示无 // 类,我们需要删除它,当我们想再次显示元素时, // 取决于toggle // 状态,所以我们在它们之间创建一个关系 if ($(this).is(".animation-helper-display-none")) { // 我在切换并且已经有了上面的类,那么// 我们希望它显示的元素,所以我们删除 // 两个类... return "visibility_ switch_off 动画助手显示无"; } else { // 这里我们只是想隐藏元素,所以我们只是 // 添加动画类,另一个将被添加 // 稍后是animationend事件... return "visibility_switch_off"; } }); }); });表 th { 背景颜色:灰色; } 表 td { 背景颜色:白色;填充:5px; } .animation-helper-display-none { 显示:无; } 表 tr .visibility_switch_off { 动画填充模式:转发;动画名称:col_hide_anim;动画持续时间:1s; } @-webkit-keyframes col_hide_anim { 0% {opacity: 1;} 100% {opacity: 0;} } @-moz-keyframes col_hide_anim { 0% {opacity: 1;} 100% {opacity: 0;} } @ -o-keyframes col_hide_anim { 0% {opacity: 1;} 100% {opacity: 0;} } @keyframes col_hide_anim { 0% {opacity: 1;} 100% {opacity: 0;} }

Name 年龄 国家
姓名 Age Country


P
Peter Mortensen

除了使用 display 之外,您还可以将元素“离屏”存储到您需要它之前,然后将其位置设置到您想要的位置并同时对其进行转换。但是,这会带来许多其他设计问题,因此您的里程可能会有所不同。

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