38

我找不到在新创建的 dom 元素上使用 css 转换的方法。

假设我有一个空的 html 文档。

<body>
    <p><a href="#" onclick="return f();">click</a></p>
</body>

我也有这个CSS

#id {
    -moz-transition-property: opacity;
    -moz-transition-duration: 5s;
    opacity: 0;
}

#id.class {
    opacity: 1;
}

而这个js

function f() {
    var a = document.createElement('a');
    a.id = 'id';
    a.text = ' fading in?';
    document.getElementsByTagName('p')[0].appendChild(a);
    // at this point I expect the span element to be with opacity=0

    a.className = 'class';
    // now I expect the css transition to go and "fade in" the a        

    return false;
}

但是,正如您在http://jsfiddle.net/gwxkW/1/上看到的那样,当您单击该元素时会立即出现。

如果我尝试在 a 中设置类,timeout()经常会找到结果,但对我来说,这似乎更像是 javascript 和 css 引擎之间的竞赛。有什么特定的事件要听吗?我尝试使用document.body.addEventListener('DOMNodeInserted', ...),但它不工作。

如何在新创建的元素上应用 css 过渡?

4

3 回答 3

40

在 Firefox 中,这似乎是布局完成和 CSS 转换之间的竞赛。Chrome 更具可预测性。如果我在 a 上设置类名setTimeout(),Chrome 总是可以工作,Firefox 只有在setTimeout()时间很长的情况下才能工作。

在 Firefox 中使用此代码(即使使用setTimeout()),文本会立即显示:

function f() {
    var a = document.createElement('a');
    a.id = 'id';
    a.innerHTML = ' fading in?';
    document.getElementsByTagName('p')[0].appendChild(a);
    // at this point I expect the span element to be with opacity=0

    setTimeout(function() {
        a.className = 'fadeIn';
    }, 10);
    return false;
}

但是,如果我通过请求一个只能在布局后返回的属性来强制重排,它就会开始在 Firefox 中工作:

function f() {
    var a = document.createElement('a');
    a.id = 'id';
    a.innerHTML = ' fading in?';
    document.getElementsByTagName('p')[0].appendChild(a);
    // at this point I expect the span element to be with opacity=0

    // request property that requires layout to force a layout
    var x = a.clientHeight;
    setTimeout(function() {
        a.className = 'fadeIn';
    }, 10);
    return false;
}

此外,一旦我请求该属性强制布局,我什至可以删除该属性,setTimeout()并且动画在 Firefox 中有效。

function f() {
    var a = document.createElement('a');
    a.id = 'id';
    a.innerHTML = ' fading in?';
    document.getElementsByTagName('p')[0].appendChild(a);
    // at this point I expect the span element to be with opacity=0

    // request property that requires layout to force a layout
    var x = a.clientHeight;
    a.className = 'fadeIn';
    return false;
}

您可以在 Chrome 和 Firefox 中看到最后一项工作:http: //jsfiddle.net/jfriend00/phTdt/

而且,这里有一篇文章讨论了这种现象: http: //gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html

于 2012-08-23T10:04:17.747 回答
16

在将元素附加到 DOM 之后,我找到了一种更好的方法来触发布局并使转换工作:

window.getComputedStyle(element).opacity;
于 2014-06-30T13:13:12.927 回答
8

requestAnimationFrame()( https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame ) 似乎适用于 Firefox、Chrome 和 Safari。一个更可靠、更合乎逻辑的解决方案setTimeout()。对于较旧的浏览器(IE8),它需要一个 Polyfill(自然不会发生过渡,但 CSS 仍会更改)。

于 2014-12-22T20:20:03.597 回答