问题
when I click the window, CSS transition is not trigger.
const div = document.querySelector('div');
window.onclick = function() {
div.classList.add('fade');
div.classList.add('in');
}
.fade {
opacity: 0;
}
.fade.in {
transition: opacity 2s linear;
opacity: 1;
}
<div>aaaa</div>
then I change the script, use setTimeout
to add the second class in
, it works.
const div = document.querySelector('div');
window.onclick = function() {
div.classList.add('fade');
setTimeout(function() {
div.classList.add('in');
});
}
.fade {
opacity: 0;
}
.fade.in {
transition: opacity 2s linear;
opacity: 1;
}
<div>aaaa</div>
so I think, is nees a period time between CSS property change can trigger CSS transition?
so i add the time between add classes. it also not work.
<script>
window.onclick = function(){
div.classList.add('fade');
for(var i=0;i<10000; i++){
console.log(i);
}
div.classList.add('in');
}
</script>
why change classes in a same function can not trigger a css transition?
回答1:
If we go deeper in working of JavaScript V8 engine, the execution could be broken down which could clarify the current behavior. JavaScript is single threaded, more precisely
one thread == one call stack == one thing at a time
As shown above setTimeout is part of WebAPIs which comes within browser. The priority of WebAPIs is lower than 'stack' methods which are core JavaScript functions.
As mentioned above "This is the crucial part: making multiple changes to an element's classList does not cause the element to be redrawn with each change"
The reason for this is "Render Queue" which is functional part of V8 architecture as shown below:
The rendering happens between the 'stack' method execution. After all the stack is empty 'event loop' is triggered and it pulls any method which was passed to WebAPIs. This is the reason, in second scenario when the script is changed to use setTimeout, it works.
More detailed explanation of this can be seen on Philip Roberts blog
https://youtu.be/8aGhZQkoFbQ
回答2:
The transition must be defined for the div
with the initial state of the opacity (in this case zero).
const div = document.querySelector('div');
window.onclick = function() {
div.classList.add('fade');
div.classList.add('in');
}
div {
opacity: 0;
transition: opacity 2s linear;
}
.fade {}
.fade.in {
opacity: 1;
}
<div>aaaa</div>
回答3:
In your first example, you're adding both classes to the element simultaneously before the element gets redrawn. The initial value of opacity is 1, and the opacity of .fade.in
is also 1, so there is no change in the element's opacity.
This is the crucial part: making multiple changes to an element's classList does not cause the element to be redrawn with each change.
Delaying the addition of the "in" class means the browser first has to render the element as simply .fade
, with an opacity of 0. After the timeout, the browser realizes it needs to transition the element's opacity from 0 to 1, so it performs the necessary interpolation.
来源:https://stackoverflow.com/questions/45275438/css-transition-is-not-trigger-by-add-classes-in-a-same-function