Das liegt daran, dass das Element erst gerendert wird, wenn deine JavaScript-Operation abgeschlossen ist.
Element einfügen und direkt danach die „neue“ Breite setzen = Element wird gleich mit der vermeintlich neuen Breite gerendert, ergo findet keine Veränderung statt, die die Transition auslösen könnte.Mit setTimeout startet du einen neuen Ausführungskontext – der alte wird erst mal beendet, damit die Kontrolle an die Rendering-Engine zurück gegeben, und das Element mit der ursprünglichen Breite gerendert. Und der zeitversetzte Aufruf des Breite-Änderns ändert dann anschließend *tatsächlich* die Elementbreite.
Auch von mir ein dickes Danke für die Erleuchtung.