CSS显示属性的转换

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

目前,看来CSS 3转换不适用于“显示”属性,即,你不能做任何从display: nonedisplay: block(或任何组合)的转换。

当有人将鼠标悬停在一个顶级菜单项上时,是否有一种方法可以让上面示例中的第二层菜单“淡入”?

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

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

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

2201683 次浏览

而不是使用display,你可以将元素“离屏”存储到你需要它的地方,然后将其位置设置为你想要的位置并同时转换它。这带来了一大堆其他设计问题,所以因人而异。

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

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

我通过绝对定位<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;}

您可以连接两个或多个转换,这次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属性的供应商前缀。)

更多细节在这篇文章

display不是转换工作的属性之一。

有关可以对其应用转换的CSS属性列表,请参阅动画CSS属性。有关它们的插值方式,请参阅CSS值和单元模块第4级,组合值:插值、加法和累加

直到CSS 3在9.1。CSS中的属性中列出(只需关闭警告弹出窗口)

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

上次我不得不这样做,我用max-height代替,这是一个可动画的属性(虽然它有点黑客,它确实有效),但要注意,对于复杂的页面或使用低端移动设备的用户来说,它可能非常简陋。

在这篇文章的时候,如果您尝试更改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 CSSdocument.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>

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

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

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

我今天遇到了这个,我重用了一个position: fixed模式。我不能保留它display: none,然后对它进行动画处理,因为它刚刚出现,z-index(负值等)也做了奇怪的事情。

我也使用了height: 0height: 100%,但它只有在模态出现时才起作用。这与你使用left: -100%或其他东西是一样的。

然后我突然想到有一个简单的答案。

首先,您隐藏的模态。请注意height0,并检查转换中的height声明…它有500ms比我的#4过渡还长。请记住,这会影响传出的淡出转换:将模态返回到其默认状态。

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

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

我怀疑如果display被更改,转换被禁用的原因是因为显示的实际作用。它确实改变了任何可以想象的平滑动画的东西。

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

display: none另一方面实际上防止渲染完全中的元素。
它不占用任何布局空间。
其他可能占用此元素占用的部分或全部空间的元素现在调整为占用该空间,就好像元素只是根本就不存在一样。

display不仅仅是另一个视觉属性。
它建立了元素的整个渲染模式,例如它是blockinlineinline-blocktabletable-rowtable-celllist-item还是其他什么!
每一个都有非常不同的布局后果,并且没有合理的方法来动画或平滑地过渡它们(例如,尝试想象从blockinline的平滑过渡,反之亦然!)。

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

这个问题最简单的通用解决方案是:随意在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或更早版本中工作。

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

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

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

  var tTimeout;element.addEventListener("transitionend", afterTransition, true);//firefoxelement.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;}

它工作,到目前为止!

您可以简单地使用CSS知名度:隐藏/可见而不是显示:无/块

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

你也可以使用这个:

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

从这些答案和其他地方的一些建议中,以下内容非常适合悬停菜单(我在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可能。

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

  • 超文本标记语言:

    <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 for testing:

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

Note that if you just make the link transparent, without setting visibility: hidden, then it would stay clickable.

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

超文本标记语言

<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 ulmax-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

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

@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,并且仍然设法淡入淡出。

在吉列尔莫接受的答案写完后,CSS2012-04-03的转换规范更改了可见性转换和现在用更短的方法解决这个问题是可能的的行为,而不使用过渡延迟:

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

为两个转换指定的运行时间通常应该是相同的(虽然能见度稍长的时间不是问题)。

有关运行版本,请参阅我的博客文章CSS转换可见性

W. r. t.问题"显示器上的过渡:属性"的标题以及对Rui Marques和josh对已接受答复的评论的答复:

此解决方案适用于情况,如果显示或显示不相关可见性属性使用(因为在这个问题中可能是这种情况)。

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

完全删除类似于display:none的元素的过渡可以使用高度(如其他答案和注释所示)、max-高度或边际顶部/底部完成,但也请参阅如何过渡高度:0;高度:自动;使用CSS?和我的博客文章显示和高度属性上CSS转换的解决方法

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

我认为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 downelement.className = element.className + " push-down";

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

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

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

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

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

这里有两个例子:https://jsfiddle.net/qwnz9tqg/3/

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

.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;来确保隐藏容器不占用空间不回答用户交互

你可以让它以你预期的自然方式工作——使用显示——但是你必须限制浏览器才能让它工作,使用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 });elsetag.css({ opacity: 0 });});

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

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

请注意,在淡出动画结束时,上面不会再次将显示设置为无。不过,我们可以变得更花哨。让我们使用一个淡入并从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/动画队列,而不需要任何现在在jQuery 3. x中被排除在外的动画框架。我不打算解释jQuery是如何工作的,但足以说,jQuery提供的.queue().stop()管道帮助我们防止我们的动画相互踩踏。

让我们动画幻灯片效果。

$('#button').on('click', function() {var tag = $('#box');if (tag.hasClass('hidden')) {// Open it// Measure ittag.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 itvar 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类。如果它实际上是隐藏的,你会期望找到它——这是上面更简单的示例无法做到的。这碰巧还启用了一遍又一遍地显示/隐藏元素,这在前面的示例中是一个bug,因为隐藏的类从未恢复。

您还可以看到在.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毫秒或2000毫秒的延迟,在这个队列上,其他程序员很容易找到/解决。

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

试试下面的片段…

$(document).ready(function() {// Assign transition event$("table").on("animationend webkitAnimationEnd", ".visibility_switch_off", function(event) {// We check if this is the same animation we wantif (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>

它可以通过使用转换定时函数step-endstep-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>

我开始了一个名为[切换显示动画][1]的开源骨架项目。

这个骨架助手将允许您轻松模仿jQuery显示/隐藏,但使用输入/输出CSS 3过渡动画。

它使用类切换,因此您可以在除了显示之外的元素上使用任何您想要的CSS方法:无|块|表|内联等,以及可以想到的其他替代用途。

它的主要设计目的是元素切换状态,它支持恢复状态,其中隐藏对象允许您反向运行关键帧或播放替代动画来隐藏元素。

我正在研究的概念的大部分标记都是CSS,实际使用的JavaScript很少。

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

.block {opacity: 1;transition: opacity 250ms ease;}
.block--invisible {pointer-events: none;opacity: 0;}

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

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

.toggle {opacity: 0;position: absolute;transition: opacity 0.8s;}
.parent:hover .toggle {opacity: 1;position: static;}

而不是CSS中不存在的回调,我们可以使用transition-delay属性。

#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 ms),尽管height需要0 ms才能完成动画(相当于display: block),opacity需要600 ms。

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

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

有关更多示例,请参阅这篇文章

如果您使用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以外的显示值(就像.fadeIn().fadeOut()的默认值一样)。

在这里,我正在过渡到显示flex,具有很好的淡入淡出效果。

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

事实证明visibility CSS属性的值collapse通常用于表项。但是,如果在任何其他元素上使用,它实际上会将它们呈现为隐藏,与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>

它就像下面这样简单:)

@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;。还要确保使用前向,以便它保持在最终状态。

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

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

.className{visibility:hidden;opacity: 0;transition: .2s;width:0;}
.className:hover{visibility:visible;margin-right: .5rem;opacity: 1;width:unset;}

CSS动画淡入:

.item {display: none;}
.item:hover {display: block;animation: fadeIn 0.5s;}
@keyframes fadeIn {from {opacity: 0;}
to {opacity: 1;}}

我很欣赏所有的答案。这是我用于类似目的的东西:过渡与动画。

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

在我的例子中,我使用JQuery切换函数来管理元素的可见性,所以我没有使用css处理转换,而是使用滑动切换来管理可见性并处理转换部分。

<!doctype html><html lang="en"><head><meta charset="utf-8"><title>slideToggle demo</title><style>p {width: 400px;}</style><script src="https://code.jquery.com/jquery-3.5.0.js"></script></head><body> 
<button id="toggle-button">Toggle</button><button id="slide-toggle-button">Slide Toggle</button><p>This is the paragraph to end all paragraphs.  Youshould feel <em>lucky</em> to have seen such a paragraph inyour life.  Congratulations!</p> 
<script>$( "#toggle-button" ).click(function() {$( "p" ).toggle();});$( "#slide-toggle-button" ).click(function() {$( "p" ).slideToggle( "slow" );});</script> 
</body></html>

总的来说,我找到了最好的解决方案:使用负上边距而不是display:none

对我来说效果很好的解决方案是使用负上边距——边距对动画/过渡有效——在我的transform过渡后将菜单从页面顶部移开。对我来说,其中一个问题是即使使用visibility隐藏它也会占用空间,下面的解决方案(结合绝对定位)解决了这个问题。这样做(出于语义目的将可见性设置为hidden)几乎和给它display:none一样好。然而,请注意,下面的可见性设置是可选,真正的工作是由负边距完成的。

我喜欢这个解决方案,因为它避免了JavaScript——你可以看到我正在使用一个input元素(隐藏在汉堡图标下面)来隐藏/取消隐藏从屏幕左侧滑入的菜单。一个小小的烦恼是不得不使用一个“任意大的数字”作为负边距,但它运行得很好。在我看来,唯一完全干净的解决方案是支持转换,以支持像display这样的事情,其中转换只是等待延迟,然后立即转换,但根据当前的CSS标准规范,这是我最好的解决方案:

css

#menu {/* Hide menu */position: absolute;overflow: hidden;
margin: -99999px 0 0 -50px;padding: 0;visibility: hidden;transform-origin: 0% 0%;transform: translate(-100%, 0);
transition: margin 0s 0.5s, padding 0s 0.5s, visibility 0s 0.5s, transform 0.5s cubic-bezier(0.77, 0.2, 0.05, 1.0);}#menuToggle input:checked~#menu {/* Display menu */overflow: unset;
margin: -80px 0 0 -50px;padding: 125px 50px 25px 50px;visibility: unset;transform: none;
transition: margin 0s 0s, padding 0s 0s, visibility 0s 0s, transform 0.5s cubic-bezier(0.77, 0.2, 0.05, 1.0);}

超文本标记语言

<div id="menuToggle"><input type="checkbox" id="chkBurgerMenu" /><span></span><span></span><span></span><ul class="navbar-nav"><li><a href="#" class="nav-link"">Home</a></li><li><a href="#" class="nav-link"">Link1</a></li><li><a href="#" class="nav-link"">Link2</a></li></ul></div>