2012-08-23 81 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