2012-08-23 80 views
33

我找不到在新创建的dom元素上使用css转换的方法。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/当您单击元素瞬间出现。

如果我尝试设置类timeout()经常找到结果,但对我来说,它似乎更多的JavaScript和CSS引擎之间的种族。是否有一些特定的事件要听?我试图使用document.body.addEventListener('DOMNodeInserted', ...),但它不工作。

如何在新创建的元素上应用css转换?

+0

使用'setTimeout'设置类名称的作用,但只有当我的延迟是6ms或更多。不确定一个好方法。 – pimvdb

+0

是的,我尝试了一些低毫秒值(范围0-10),大部分时间它的工作时间为5-6毫秒,但我感觉这是错误的方法。我希望的是某种事件涉及到“从现在开始应用CSS”,但我不知道它们是否存在 –

+0

请参见http:// stackoverflow。com/questions/18564942/clean-way-to-programmatically-use-css-transitions-from-js讨论一个干净的方式来做到这一点。 – Nickolay

回答

37

在Firefox中,它似乎是布局完成和CSS转换之间的竞争。 Chrome更具可预测性。如果我在setTimeout()上设置类名称,则Chrome始终可用,只有当setTimeout()时间较长时,Firefox才能正常工作。

有了这个代码在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和火狐在这里看到这最后一个工作:http://jsfiddle.net/jfriend00/phTdt/

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

+0

感谢您的链接:虽然我发现这个解决方案有点* hackish *至少它明显的动机 –

+0

财产技巧不适用于多个项目,但是;只有延迟了。 –

12

我发现触发布局的更好的方式和使转换工作只是元素附加到DOM后:

window.getComputedStyle(element).opacity; 
+1

Tim Taubert在本文底部也讨论了这个解决方案:https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically-created-dom-elements/ – robocat

+1

我不会使用'.cssText',虽然它很沉重(将所有样式序列化)。 – Nickolay

+0

只需使用'.opacity',不管怎样这都应该使用,因为这是应该由渲染引擎 – timaschew