6

我想对已display: none设置的元素进行 css 转换。考虑以下代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>CSS Transition From Hidden</title>

        <style type="text/css">
            div {
                -webkit-transition-property: all;
                -webkit-transition-duration: 2s;
            }       

            div.hidden {
                display: none;
                opacity: 0;
            }    

            div.from {
                opacity: 0;
            }
        </style>     

        <script type="text/javascript">
            function loaded() {
                var e = document.getElementById("foo");
                e.className = "from";
                window.webkitRequestAnimationFrame(function(t) {
                    e.className = null;
                });
            }
        </script>
    </head>
    <body onload="loaded()">
        <div id="foo" class="hidden">
            My test div
        </div>
    </body>
</html>

我想从class="div.hidden"to class="",即从display: none; opacity: 0;todisplay: block; opacity: 1;但是,在 chrome 中(至少)一个display: none没有动画的对象。元素立即进入结束状态。

我的解决方法是首先将元素设置为display: block; opacity: 0;,然后在下一帧中进行转换(使用. 这有点尴尬,我在规范requestAnimationFrame()中找不到这种行为的任何解释。我知道我可以使用-属性,但我不想使用它,因为我不想布局隐藏元素。visibility

所以,问题是:这是正确的行为还是错误?如果这是正确的行为,是否有更好的方法来编写代码?请注意,我不是在问是否有任何库可以做到这一点,我想知道是否有更好的方法可以直接在 DOM 上做到这一点。

4

6 回答 6

7

关于这是否在规范中的问题,这里的 www-style@w3.org 列表中有一个有趣的线程。我还没有读完它,但似乎他们没有从动画开始,none并且过渡规范也需要澄清这一点。

更新:我已经询问了邮件列表,并且我得到了工作组会议记录的链接,在该会议记录中决定如果开始状态是不应该有过渡display: none

要确保执行转换,您必须确保在将动画属性设置为新目标之前计算动画属性的值。当显示设置为无时,通常不计算值。这是一个工作示例:

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">

    <title>Fade</title>

    <style>
      .hidden { display: none }
      .start { opacity: 0 }
      .transition { opacity: 1; -webkit-transition: opacity 1s }
    </style>
  </head>
  <body>
    <div id='div' class="hidden">Test</div>

    <script>
      var elem = document.getElementById('div');

      function ontransitionend(event) {
        elem.className = null;
        elem.removeEventListener('transitionend', ontransitionend);
      }
      elem.addEventListener('transitionend', ontransitionend);

      elem.className = 'start';
      window.getComputedStyle(elem).opacity;
      elem.className = 'transition';
    </script>
  </body>
</html>

请注意,您必须访问 opacity 属性。打电话是不够的getComputedStyle()

于 2012-11-19T10:31:30.307 回答
2

您不一定要中继transitionend回调。
要在 opacity 属性(或其他属性)上显示最初具有 的隐藏元素display:none,只需使用内联样式设置display:block然后删除您的 CSS 类.hidden以根据需要为元素设置动画:

CSS:

#foo {
    display: none;
    opacity: 1;
    /*optional, other ending properties...*/
    transition: opacity 1s;
}
.hidden {
    opacity: 0;
    /*optional, other starting properties...*/
}

HTML:

<div id="foo" class="hidden">
    My test div
</div>

最后,用过渡显示元素的 javascript 部分:

var elem = document.getElementById('foo');
elem.style.display = 'block';
elem.classList.remove('hidden');
于 2013-11-22T16:23:42.837 回答
1

有几个 css 属性不能以小步长递增(和display之间的 25% 的值是多少?),尤其是那些具有非数值的属性。您描述的解决方法几乎是处理此问题的标准方法。例如,jQuery 在其和方法中使用了类似的东西。noneblockfadeInfadeOut

如果你想动画从不占用空间到标准布局的过渡,你可以过渡heightwidth属性。

于 2012-11-19T09:59:09.767 回答
1

display: none 意味着您可以到达该元素,但首先您应该确保该元素已被渲染。您可以在 jquery 中使用 ready 函数或在 javascript 中实现它以确保元素存在。您可以使用以下方法执行上述操作:javascript(使用计时器增加不透明度)或 jquery

<html>
    <head>
        <meta charset="utf-8">
        <title>CSS Transition From Hidden</title>

    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
        <style type="text/css">

            div.hidden {
                display: none;
                opacity: 0;
            }    

                    </style>     

        <script type="text/javascript">
$.ready = function () {

                $("#foo").fadeIn(2000);

            }
        </script>
    </head>
    <body>
        <div id="foo" class="hidden">
            My test div
        </div>
    </body>
</html>
于 2012-11-19T10:23:52.393 回答
1

我有同样的问题,我认为浏览器不应该将其视为可接受的行为。问题不在于有人试图为实际的显示属性设置动画。它不能让元素具有显示:无,将属性更新为内联或其他内容,然后为不透明度设置动画,例如,即使您在显示更新后将超时设置为 10 秒也不行。

我现在的解决方法是将宽度和高度设置为 0,溢出到隐藏,更新这些值,然后更新动画属性。至少它的行为更像是显示不显示而不是隐藏可见性。

于 2014-07-23T23:43:09.413 回答
0

display:none 提升动画效果。很遗憾,我认为应该由浏览器解决。我之前通过将 z-index 设置为 -1 来解决这个问题,这会隐藏元素,如果绝对定位也会将其从静态布局中删除。您实际上可以转换 z-index(虽然它看起来不像动画),因此不会弄乱不透明动画。

这在我的应用程序上对我有用,尽管我最终不得不使用 JavaScript 将显示属性从无设置为阻塞,因为我最终需要在溢出:自动元素中使用淡入淡出元素,当它没有被隐藏时,在不希望的时间创建滚动条。

于 2013-06-25T13:13:01.240 回答