Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript/CSS: Delay between adding element to DOM and its CSS rules being applied?

Tags:

javascript

css

I am using JavaScript to dynamically add an element to the DOM. I want to use CSS3 transitions to "fade in" the element as it is added.

I am using something like the following to achieve this:

function add(el) {

    el.className += ' fader';
    el.style.opacity = 0;

    document.getElementById('parent-element').appendChild(el);
    //setTimeout(function () { el.style.opacity = 1; }, 5);
    el.style.opacity = 1;

}

And the CSS:

.fader {
    -webkit-transition: opacity 0.5s;
}

This does not work as expected - the element does not fade in. If I replace the line el.style.opacity = 1; with setTimeout(function () { el.style.opacity = 1; }, 5);, as seen commented-out above, it does work as expected.

I am guessing that the first case does not work as there is some delay between adding the element and the appropriate CSS rules being applied to it. The 5ms delay created by the setTimeout in the second case gives enough time for these rules to be applied, therefore the fade takes place as expected.

Firstly, is this a correct assumption? Secondly, is there a better way to solve this? The setTimout feels like a hack. Is there perhaps some event that is fired once the element has had all its styles applied?

like image 672
oogles Avatar asked Oct 08 '22 12:10

oogles


1 Answers

For a CSS3 transition to work, the object has to exist in a particular state and then you have to make a change to the object that triggers the transition.

For a variety of reasons, all of my experience with CSS3 transitions has shown me that a state that counts for this is only a state that it exists in when your javascript returns and the browser goes back to its event loop. It's as if, the only way you can tell the browser to loop at your object now and remember it's state for future transitions is to go back to the browser event loop. There are some programming reasons why this may be the case (so it's not trying to execute transitions as you're programmatically building your object and changing it), but those issues could have been solved a different way (like with a specific method call to codify the object now), but it wasn't done that way.

As such, your solution is the way I've found to do it. Create the object in it's initial state. Set a timer for a very short duration. Return from all your javascript so the object will get codified in its initial state and so the timer can fire. In the timer event, add a class to the object that triggers the CSS3 transition.

I don't honestly know if CSS3 transitions are specified this way in the specification, but my experience in Safari, Firefox and Chrome has been that this is how they work.

like image 87
jfriend00 Avatar answered Oct 12 '22 01:10

jfriend00