CSS display 属性上的转换
Posted
技术标签:
【中文标题】CSS display 属性上的转换【英文标题】:Transitions on the CSS display property 【发布时间】:2011-03-20 20:51:48 【问题描述】:我目前正在设计一个 CSS 'mega dropdown' 菜单 - 基本上是一个常规的纯 CSS 下拉菜单,但包含不同类型的内容。
目前,似乎 CSS 3 过渡不适用于“显示”属性,也就是说,您无法进行从 display: none
到 display: block
的任何类型的过渡(或任何组合)。
当有人将鼠标悬停在***菜单项之一上时,是否有办法让上例中的二级菜单“淡入”?
我知道您可以在 visibility:
属性上使用转换,但我想不出一种有效使用它的方法。
我也尝试过使用高度,但是失败得很惨。
我也知道使用 javascript 实现这一点很简单,但我想挑战自己只使用 CSS,但我想我有点短。
【问题讨论】:
位置:绝对;可见性:隐藏;等同于 display: none; @Jawad:仅当您也添加类似z-index:0
的内容时。
@Jawad:建议不要使用visibility: hidden
,除非您想要屏幕阅读器来阅读它(而典型的浏览器不会)。它只定义了元素的可见性(就像说opacity: 0
),它仍然是可选择的、可点击的,和以前一样;它只是不可见。
在 IE 8,9,10 中不支持 pointer-events
,所以它并不总是可以的
你需要显示:none 否则你会绊倒触发器外的隐藏对象,它会意外显示...我只是说:)
【参考方案1】:
我启动了一个名为 [Toggle Display Animate][1] 的开源框架项目。
这个骨架助手将允许您轻松模仿 jQuery 显示/隐藏,但带有输入/输出 CSS 3 过渡动画。
它使用类切换,因此您可以在元素上使用任何您想要的 CSS 方法,除了 display:none|block|table|inline 等,以及可以想到的其他替代用途。
它的主要设计目的是用于元素切换状态,它支持还原状态,在这种状态下隐藏对象允许您反向运行关键帧或播放替代动画来隐藏元素。
我正在研究的概念的大部分标记是 CSS,实际使用的 JavaScript 很少。
【讨论】:
【参考方案2】:感谢所有答案。这是我用于类似目的的内容:过渡与动画。
示例: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);
【讨论】:
【参考方案3】:我们可以使用 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;
那么,这里发生了什么?
当添加visible
类时,height
和 opacity
都会立即开始动画(0 ms),但 height
需要 0 ms 才能完成动画(相当于 display: block
)和 opacity
需要600 毫秒。
当visible
类被移除时,opacity
开始动画(0 毫秒延迟,400 毫秒持续时间),高度等待 400 毫秒,然后才立即(0 毫秒)恢复初始值(相当于 display: none
在动画回调)。
注意,这种方法比使用visibility
的方法要好。在这种情况下,元素仍然占据页面空间,并不总是合适的。
更多示例请参考this article。
【讨论】:
它只适用于height:100%
,在某些情况下会破坏布局。很好的解决方案,如果这不是问题的话。为数不多的双向工作之一。
你必须设置一个高度 - 设置height: auto
使它立即消失。【参考方案4】:
用CSS Animations淡入:
.item
display: none;
.item:hover
display: block;
animation: fadeIn 0.5s;
@keyframes fadeIn
from
opacity: 0;
to
opacity: 1;
【讨论】:
【参考方案5】:我找到了解决这个问题的更好方法,您可以使用 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)
【讨论】:
【参考方案6】:在这种情况下不使用关键帧应用过渡的另一种方法是将元素的宽度设置为零,然后取消设置悬停时
.className
visibility:hidden;
opacity: 0;
transition: .2s;
width:0;
.className:hover
visibility:visible;
margin-right: .5rem;
opacity: 1;
width:unset;
【讨论】:
【参考方案7】:我怀疑如果 display
更改,过渡被禁用的原因是因为显示实际做了什么。它确实不会改变任何可以想象的平滑动画。
display: none;
和 visibility: hidden;
是两个完全不同的东西。
两者都具有使元素不可见的效果,但使用 visibility: hidden;
时,它仍会在布局中呈现,只是不是可见。
隐藏元素仍然占用空间,并且仍然内联或作为块或块内联或表格或display
元素告诉它渲染为的任何内容呈现,并相应地占用空间。
其他元素不会自动移动以占据该空间。隐藏元素只是不会将其实际像素渲染到输出。
display: none
实际上阻止元素渲染完全。
它不占用任何布局空间。
原本会占用该元素所占用的部分或全部空间的其他元素现在会调整以占用该空间,就好像该元素根本根本不存在一样。
display
不仅仅是另一个视觉属性。
它建立了元素的整个渲染模式,例如它是否是block
、inline
、inline-block
、table
、table-row
、table-cell
、list-item
,等等!
它们中的每一个都有非常不同的布局分支,并且没有合理的方法来为它们设置动画或平滑过渡(例如,尝试想象从 block
到 inline
的平滑过渡,反之亦然!)。
这就是为什么在显示更改时禁用过渡的原因(即使更改是来自none
或来自none
不仅仅是不可见,它是它自己的元素渲染模式,这意味着根本不渲染!)。
【讨论】:
这是正确的。这不是很明显,但是一旦您考虑一下,您很快就会意识到转换display
属性不可能工作。
与上述解决方案一样好,对于为什么过渡不适用于显示属性得到一个合理的解释是非常令人满意的。
我不同意。这完全有道理。如果 display:none 到 display:block 在转换开始时立即发生,那就太好了。对于向后过渡,如果它在过渡结束时从 display:block 变为 display:none,那将是完美的。【参考方案8】:
你可以让它以你期望的自然方式工作 - 使用显示 - 但你必须限制浏览器才能让它工作,使用 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://***.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
类,它将 display
从 none
翻转为其默认值 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 和类更改,以通常为动画设置舞台,包括进行测量,例如测量 #box
的最终高度而不向用户显示,然后调用.resumeTrnsn()
,并将其从完全设置的阶段设置为目标 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 毫秒或 2000 毫秒的延迟,在此基础上构建的其他编码人员很容易找到/解决。
【讨论】:
【参考方案9】:就这么简单:)
@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 使其保持在最终状态。
【讨论】:
【参考方案10】:您可以使用转换事件来做到这一点,因此您为转换构建了两个 CSS 类,一个保存动画,另一个保存显示无状态。你在动画结束后切换它们?在我的情况下,如果我按下一个按钮,我可以再次显示 div,并删除这两个类。
试试下面的 sn-p...
$(document).ready(function()
// Assign transition event
$("table").on("animationend webkitAnimationEnd", ".visibility_switch_off", function(event)
// We check if this is the same animation we want
if (event.originalEvent.animationName == "col_hide_anim")
// After the animation we assign this new class that basically hides the elements.
$(this).addClass("animation-helper-display-none");
);
$("button").click(function(event)
$("table tr .hide-col").toggleClass(function()
// We switch the animation class in a toggle fashion...
// and we know in that after the animation end, there
// is will the animation-helper-display-none extra
// class, that we nee to remove, when we want to
// show the elements again, depending on the toggle
// state, so we create a relation between them.
if ($(this).is(".animation-helper-display-none"))
// I'm toggling and there is already the above class, then
// what we want it to show the elements , so we remove
// both classes...
return "visibility_switch_off animation-helper-display-none";
else
// Here we just want to hide the elements, so we just
// add the animation class, the other will be added
// later be the animationend event...
return "visibility_switch_off";
);
);
);
table th
background-color: grey;
table td
background-color: white;
padding: 5px;
.animation-helper-display-none
display: none;
table tr .visibility_switch_off
animation-fill-mode: forwards;
animation-name: col_hide_anim;
animation-duration: 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;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<theader>
<tr>
<th>Name</th>
<th class='hide-col'>Age</th>
<th>Country</th>
</tr>
</theader>
<tbody>
<tr>
<td>Name</td>
<td class='hide-col'>Age</td>
<td>Country</td>
</tr>
</tbody>
</table>
<button>Switch - Hide Age column with fadeout animation and display none after</button>
【讨论】:
【参考方案11】:这个方案兼容性很好,我还没见过:
.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;
的组合来确保隐藏容器不占用空间并且不响应用户交互。
【讨论】:
【参考方案12】:我认为 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";
【讨论】:
【参考方案13】:Guillermo 接受的答案写完后,CSS 2012-04-03 的过渡规范改变了可见性过渡的行为,现在可以在不使用过渡延迟的情况下以更短的方式解决此问题:
.myclass > div
transition:visibility 1s, opacity 1s;
visibility:hidden; opacity:0
.myclass:hover > div
visibility:visible; opacity:1
为两个转换指定的运行时间通常应该是 相同(尽管可见时间稍长一点也不成问题)。
有关运行版本,请参阅我的博文CSS Transition Visibility。
W.r.t.问题的标题“显示器上的转换:属性”,并响应来自 Rui Marques 和 josh 的 cmets 对接受的答案:
此解决方案适用于 如果显示或 使用了可见性属性(在这个问题中可能就是这种情况)。
它不会完全移除display:none
的元素,只是让它不可见,但它仍然停留在文档流中并影响后面元素的位置。
完全删除类似于display:none
的元素的转换可以使用高度(如其他答案和 cmets 所示)、最大高度或边距顶部/底部来完成,但另请参阅
How can I transition height: 0; to height: auto; using CSS? 和我的博文Workarounds for CSS Transitions on the Display and Height Properties。
回应 GeorgeMillo 的评论: 两个属性和两个过渡都是需要的: opacity 属性 用于创建淡入淡出动画和可见性 属性以避免元素仍然对鼠标做出反应 事件。视觉效果的不透明度和 可见性延迟隐藏,直到淡出完成。
【讨论】:
【参考方案14】:您现在可以向块属性添加自定义动画。
@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
,但仍会逐渐消失。
【讨论】:
除非我遗漏了什么“演示”链接不再显示子菜单转换。【参考方案15】:JavaScript 不是必需的,也不需要极大的最大高度。相反,在文本元素上设置max-height
,并使用字体相关单位,例如rem
或em
。这样,您可以设置大于容器的最大高度,同时避免菜单关闭时出现延迟或“弹出”:
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
【讨论】:
【参考方案16】:从其中一些答案和其他地方的一些建议中得出,以下内容非常适合悬停菜单(特别是我将其与 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
s 一起使用。 max-height
的悬停值需要大于菜单的height
。
【讨论】:
【参考方案17】:你也可以这样用:
.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;
【讨论】:
【参考方案18】:您可以简单地使用 CSS visibility: hidden/visible 而不是 display : 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;
【讨论】:
这会保留空间,留下一个空洞。如果你想折叠一个空间,你必须为高度或其他一些属性设置动画。【参考方案19】:该问题最简单的通用解决方案是:随意在您的 CSS 中指定 display:none
,但是您必须使用 JavaScript 将其更改为 block
(或其他任何内容),然后您还必须添加有问题的元素的一个类,它实际上使用 setTimeout() 进行转换。就是这样。
即:
<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 或更早版本中工作。
【讨论】:
这就像一个魅力,谢谢!【参考方案20】:我怀疑刚开始 CSS 过渡的任何人都会很快发现,如果您同时修改显示属性(块/无),它们就不起作用。尚未提及的一种解决方法是,您可以继续使用 display:block/none
隐藏/显示元素,但将其不透明度设置为 0,这样即使是 display:block
,它仍然不可见。
然后将其淡入,添加另一个 CSS 类,例如“on”,它将不透明度设置为 1 并定义不透明度的过渡。正如您可能已经想象的那样,您必须使用 JavaScript 将“on”类添加到元素中,但至少您仍然使用 CSS 进行实际转换。
附:如果您发现自己需要同时执行 display:block
并添加“on”类,同时使用 setTimeout 推迟后者。否则,浏览器只会看到这两种情况同时发生并禁用转换。
【讨论】:
【参考方案21】:在本文发布时,如果您尝试更改 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 代码)
// 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');
);
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;
<div class="parent">
Parent
<div class="child">
Child
</div>
</div>
【讨论】:
谢谢。上面提到的height: 0
技巧(用于过渡)似乎不起作用,因为在淡出过渡时高度设置为 0,但这个技巧似乎工作得很好。
谢谢,非常有用。但是如何淡出呢?
太棒了,但是当我在动画运行时悬停 DIV 时,它会闪烁(将不透明度更改为较低的状态)......有什么想法吗?
这个答案的第一段不太有意义。浏览器不会在您使用 display
属性的那一刻直接禁用所有转换 - 真的没有理由这样做。即使他们确实,为什么动画会起作用呢?您也不能在 CSS 动画中使用 display
属性。
是的,“改变”——我不知道为什么我在那里说“使用”。我的观点是您不能转换 或 动画 display
,但这不会阻止所有其他属性的动画,只要您不转换 to none .【参考方案22】:
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
,这是一个可动画属性(虽然它有点小技巧,但它确实有效),但要注意它对于复杂页面或使用低端移动设备的用户。
【讨论】:
【参考方案23】:您需要通过其他方式隐藏元素才能使其正常工作。
我通过绝对定位<div>
s 并将隐藏的设置为opacity: 0
来实现效果。
即使您将display
属性从none
切换到block
,也不会发生在其他元素上的转换。
要解决此问题,请始终允许元素为 display: block
,但通过调整以下任何方式隐藏元素:
-
将
height
设置为0
。
将opacity
设置为0
。
将元素定位在另一个具有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;
【讨论】:
感谢 Jim 的详尽解答。您绝对正确,如果 display: 属性发生变化,那么您的所有转换都将不起作用。真可惜——我想知道这背后的原因是什么。在旁注中,在我在原始问题中发布的同一链接上,您可以看到我在哪里。我遇到的唯一(小)问题是在 Chrome [5.0.375.125] 中页面加载时,您可以看到菜单在页面上加载元素时迅速消失。 Firefox 4.0b2 和 Safari 5.0 绝对没问题... bug 还是我错过了什么?【参考方案24】:代替使用display
,您可以将元素“离屏”存储到您需要它为止,然后将其位置设置到您想要的位置并同时对其进行转换。但是,这会带来很多其他设计问题,因此您的里程可能会有所不同。
无论如何,您可能都不想使用display
,因为您希望屏幕阅读器可以访问内容,这在很大程度上试图遵守可见性规则 - 即,如果它不应该肉眼可见,它不会作为内容显示给代理。
【讨论】:
【参考方案25】:您可以连接两个或多个转换,这次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
属性的供应商前缀。)
更多详情请见this article。
【讨论】:
是的,问题在于它背后的任何东西都会重叠,即使它不可见。我发现使用 height:0 是一个更好的解决方案 这很好,但问题是“可见性隐藏”元素仍会占用空间,而“不显示”则不会。 我可能遗漏了一些东西,但你为什么要同时改变可见性和不透明度?不会将不透明度设置为 0 隐藏元素 - 为什么还需要将可见性设置为隐藏? @GeorgeMillo 如果你只设置不透明度,元素实际上还在页面上渲染(比如你不能点击思考)。 这不应被标记为正确答案。它不处理 display 属性,正如 Rui 所说,该元素仍然占用空间,这在许多情况下是不切实际的。【参考方案26】:我遇到了一个类似的问题,但我找不到答案。一些谷歌搜索后来把我带到了这里。考虑到我没有找到想要的简单答案,我偶然发现了一个既优雅又有效的解决方案。
原来visibility
CSS 属性的值collapse
通常用于表格项。但是,如果在任何其他元素上使用它,它会有效地将它们呈现为 hidden,与 display: hidden
几乎相同,但具有元素不占用任何空间并且您仍然可以动画的附加功能有问题的元素。
下面是一个简单的例子。
function toggleVisibility()
let exampleElement = document.querySelector('span');
if (exampleElement.classList.contains('visible'))
return;
exampleElement.innerhtml = 'I will not take up space!';
exampleElement.classList.toggle('hidden');
exampleElement.classList.toggle('visible');
setTimeout(() =>
exampleElement.classList.toggle('visible');
exampleElement.classList.toggle('hidden');
, 3000);
#main
display: flex;
flex-direction: column;
width: 300px;
text-align: center;
.hidden
visibility: collapse;
opacity: 0;
transition: visibility 2s, opacity 2s linear;
.visible
visibility: visible;
opacity: 1;
transition: visibility 0.5s, opacity 0.5s linear;
<div id="main">
<button onclick="toggleVisibility()">Click Me!</button>
<span class="hidden"></span>
<span>I will get pushed back up...</span>
</div>
【讨论】:
【参考方案27】:如果你使用 jQuery 来设置你的类,这将 100% 工作:
$(document).ready(function()
$('button').click(function()
var container = $('.container');
if (!container.hasClass('active'))
container.addClass('show').outerWidth();
container.addClass('active');
else
container.removeClass('active').one('transitionend', function()
container.removeClass('show');
);
);
);
.container
display: none;
opacity: 0;
transition: opacity 0.3s ease;
.container.show
display: flex;
.container.active
opacity: 1;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button">Toggle</button>
<div class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
当然你可以只使用 jQuery .fadeIn()
和 .fadeOut()
函数,但是设置类的好处是如果你想转换到 block
以外的显示值(@987654327 的默认值@ 和 .fadeOut()
)。
在这里,我正在过渡到显示 flex
并带有很好的淡入淡出效果。
【讨论】:
【参考方案28】:我已经多次遇到这个问题,现在只是选择了:
.block
opacity: 1;
transition: opacity 250ms ease;
.block--invisible
pointer-events: none;
opacity: 0;
通过添加 block--invisible
类,整个元素将无法点击,但它后面的所有元素将因为 pointer-events:none
被所有主要浏览器支持(没有 IE
【讨论】:
【参考方案29】:我终于找到了适合我的解决方案,将opacity
与position absolute
结合使用(隐藏时不占用空间)。
.toggle
opacity: 0;
position: absolute;
transition: opacity 0.8s;
.parent:hover .toggle
opacity: 1;
position: static;
【讨论】:
【参考方案30】:可以使用转换定时函数step-end
和step-start
处理
例如:https://jsfiddle.net/y72h8Lky/
$(".run").on("click", function()
$(".popup").addClass("show");
);
$(".popup").on("click", function()
$(".popup").removeClass("show");
)
.popup
opacity: 0;
display: block;
position: absolute;
top: 100%;
bottom: 0;
left: 0;
right: 0;
z-index: 1450;
background-color: rgba(0, 175, 236, 0.6);
transition: opacity 0.3s ease-out, top 0.3s step-end;
.popup.show
transition: opacity 0.3s ease-out, top 0.3s step-start;
opacity: 1;
top: 0;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="popup"></div>
<button class="run" style="font-size: 24px;">Click on me</button>
【讨论】:
以上是关于CSS display 属性上的转换的主要内容,如果未能解决你的问题,请参考以下文章