Css transite sur de nouveaux éléments

Je ne peux pas trouver un moyen d'utiliser les transitions css sur les éléments dom nouvellement créés.

Disons que j'ai un document HTML vide.

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

J'ai aussi ce css

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

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

Mais, comme vous pouvez le voir sur http://jsfiddle.net/gwxkW/1/ lorsque vous cliquez sur l'élément apparaît instantanément.

Si j'essaie de définir la classe dans un timeout() je trouve souvent le résultat, mais pour moi, il semble plus une course entre javascript et le moteur css. Y a-t-il un événement spécifique à écouter? J'ai essayé d'utiliser document.body.addEventListener('DOMNodeInserted', ...) mais ça ne fonctionne pas.

Comment puis-je appliquer les transitions css sur les éléments nouvellement créés?

requestAnimationFrame() ( https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame ) semble fonctionner sur Firefox, Chrome et Safari. Une solution logique plus fiable qui setTimeout() . Pour les navigateurs plus anciens (IE8), il faudra un Polyfill (naturellement, la transition ne se produira pas, mais le CSS va toujours changer).

Dans Firefox, cela semble être une course entre la mise en page terminée et la transition CSS. Chrome est beaucoup plus prévisible. Si je définis le nom de la classe sur un setTimeout() , Chrome fonctionne toujours, Firefox ne fonctionne que si l'heure setTimeout() est longue.

Avec ce code dans Firefox (même en utilisant setTimeout() ), le texte s'affiche immédiatement:

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

Mais, si je force une refusion en demandant une propriété qui ne peut être retournée qu'après la mise en page, elle commence à fonctionner dans 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; } 

En outre, une fois que j'ai demandé cette propriété pour forcer une mise en page, je peux même supprimer le setTimeout() et l'animation fonctionne dans 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; } 

Vous pouvez voir ce dernier travail ici en Chrome et Firefox: http://jsfiddle.net/jfriend00/phTdt/

Et voici un article qui traite du phénomène: http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html

J'ai trouvé un moyen plus agréable de déclencher la mise en page et de faire passer les transitions juste après l'ajout de l'élément au DOM:

 window.getComputedStyle(element).opacity;