I have an element with a transition applied to it. I want to control the transition by adding a class to the element which causes the transition to run. However, if I apply the class too quickly, the transition effect does not take place.
I'm assuming this is because the .shown
is placed onto the div during the same event loop as when .foo
is placed onto the DOM. This tricks the browser into thinking that it was created with opacity: 1
so no transition is put into place.
I'm wondering if there is an elegant solution to this rather than wrapping my class in a setTimeout.
Here's a snippet:
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>
Actually, the point is not about the setTimeout, but about how the element is rendered.
The CSS transition will only appear if the element is rendered with a property value, and then this property is changed.
But once you append
the element, it does not mean that it was rendered. Simply adding a setTimeout
is not enough. Thought it may work for you, in some browser versions it won't work! (Mostly Firefox)
The point is about the element's render time. Instead of setTimeout
, you can force a DOM render by requesting a visual style property, and then changing the class:
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>
When you do DOM manipulation that that javascript relies on immediately afterwards, you need to pause javascript execution briefly in order to allow rendering to catch up, since that will be done asynchronously. All a blank setTimeout does is move the code within to the end of the current execution pipeline. The browser must complete rendering the new layout before it will obey a trigger for your transition so the setTimeout is a good idea and in my opinion the most elegant solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With