The question is published on by Tutorial Guruji team.
The following snippet creates a blue box, then turns it purple. Ideally there would be a smooth transition from blue to purple, but it’s practically instant instead. The only way I can achieve this is effect is with a timeout (see the second snippet).
let DOM = document.createElement('div'); DOM.classList.add('box'); document.body.appendChild(DOM); DOM.classList.add('purple');
.box { width: 100px; height: 100px; background-color: blue; transition: background-color 0.25s; } .box.purple { background-color: purple; }
let DOM = document.createElement('div'); DOM.classList.add('box'); document.body.appendChild(DOM); window.setTimeout(() => { DOM.classList.add('purple'); }, 100);
.box { width: 100px; height: 100px; background-color: blue; transition: background-color 0.25s; } .box.purple { background-color: purple; }
A timeout seems like a bit of a hacky solution that could fail if the machine was slow or cause excess delay on faster machines. Primarily though, I’m looking for a better solution for this problem. Is there a way to await
appendChild
so that the class is added as soon as the element has been added?
Answer
Actually any value of delay will work here. Even this works:
window.setTimeout(() => { DOM.classList.add('purple'); }, 0);
jsfiddle: https://jsfiddle.net/OscarSaharoy/x46wnehs/1/
This is because of the browser’s event loop. All normal code runs, then its effects happen, then any setTimout
functions run. So without setTimeout
around the classList.add
call, the box is added with its background-color
being purple already. But with the setTimout
, the box is added and then afterwards its background-color
changes, causing the smooth transition.
A better solution is maybe to use css keyframes, see here for an implementation using them: https://codepen.io/ericwshea/pen/EyzZQg
So you can specify in css something like animation: color-change 0.25s;
on the element you add in and also
@keyframes color-change { from { background-color: blue; } to { background-color: purple; } }
in the css body.