Pourquoi SetTimeout est-il nécessaire lorsque l'on applique une classe pour que ma transition prenne effet?

J'ai un élément avec une transition appliquée. Je veux contrôler la transition en ajoutant une classe à l'élément qui entraîne la transition à exécuter. Toutefois, si j'applique la classe trop rapidement, l'effet de transition n'a pas lieu.

Je suppose que c'est parce que le .shown est placé sur la div pendant la même boucle d'événement que lorsque .foo est placé sur le DOM. Cela empêche le navigateur de penser qu'il a été créé avec l' opacity: 1 donc aucune transition n'est mise en place.

Je me demandais s'il y avait une solution élégante à ce sujet plutôt que d'envelopper ma classe dans un setTimeout.

Voici un extrait:

 var foo = $('<div>', { 'class': 'foo' }); foo.appendTo($('body')); setTimeout(function(){ foo.addClass('shown'); }); 
 .foo { opacity: 0; transition: opacity 5s ease; width: 200px; height: 200px; background-color: red; } .foo.shown { opacity: 1; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

En fait, le point ne concerne pas SetTimeout, mais la façon dont l'élément est rendu.

La transition CSS n'apparaîtra que si l'élément est rendu avec une valeur de propriété, puis cette propriété est modifiée. Mais une fois que vous append l'élément, cela ne signifie pas qu'il a été rendu. Il suffit simplement d'ajouter un setTimeout . J'ai pensé que cela pourrait fonctionner pour vous, dans certaines versions de navigateurs, cela ne fonctionnera pas! (Principalement Firefox)

Le point concerne le temps de rendu de l'élément. Au lieu de setTimeout , vous pouvez forcer un rendu DOM en demandant une propriété de style visuel, puis en modifiant la classe:

 var foo = $('<div>', { 'class': 'foo' }); foo.appendTo($('body')); //Here I request a visual render. var x = foo[0].clientHeight; //And it works, without setTimeout foo.addClass('shown'); 
 .foo { opacity: 0; transition: opacity 5s ease; width: 200px; height: 200px; background-color: red; } .foo.shown { opacity: 1; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

Lorsque vous effectuez une manipulation DOM sur laquelle javascript s'appuie immédiatement, vous devez interrompre brièvement l'exécution de javascript afin de permettre au rendu de rattraper, car cela se fera de manière asynchrone. Tout un jeu blanc SetTimeout fait déplacer le code jusqu'à la fin du pipeline d'exécution actuel. Le navigateur doit compléter le rendu de la nouvelle mise en page avant d'obéir à un déclencheur pour votre transition afin que setTimeout soit une bonne idée et, à mon avis, la solution la plus élégante.