Indeed, addClass
operates synchronously. By examining the source code:
addClass: function( value ) {
var classes, elem, cur, curValue, clazz, j, finalValue,
i = 0;
if ( jQuery.isFunction( value ) ) {
return this.each( function( j ) {
jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
} );
}
if ( typeof value === "string" && value ) {
classes = value.match( rnothtmlwhite ) || [];
while ( ( elem = this[ i++ ] ) ) {
curValue = getClass( elem );
cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
if ( cur ) {
j = 0;
while ( ( clazz = classes[ j++ ] ) ) {
if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
cur += clazz + " ";
}
}
// Only assign if different to avoid unneeded rendering.
finalValue = stripAndCollapse( cur );
if ( curValue !== finalValue ) {
elem.setAttribute( "class", finalValue );
}
}
}
}
return this;
}
The same outcome can be achieved using native APIs rather than jQuery.
var elem = document.getElementById('elem');
elem.classList.remove('transition');
elem.style.left = '200px';
elem.classList.add('transition');
elem.style.left = '0px';
#container {
position: relative;
width: 400px;
height: 200px;
background-color: red;
}
#elem {
width: 50px;
height: 50px;
position: relative;
left: 0;
top: 0;
background-color: blue;
}
.transition.linear.scritta {
-webkit-transition: all 1.0s linear;
-moz-transition: all 1.0s linear;
-ms-transition: all 1.0s linear;
-o-transition: all 1.0s linear;
transition: all 1.0s linear;
}
<div id="container">
<div id="elem" class="transition linear scritta"></div>
</div>
Browsers delay direct updates when modifying CSS styles to optimize performance, preventing unnecessary renderings and layouts that are costly when multiple style changes are involved.
To work around this limitation, consider employing asynchronous code:
requestAnimationFrame(function() {
elem.style.left = '0px';
});
var elem = document.getElementById('elem');
elem.classList.remove('transition');
elem.style.left = '200px';
elem.classList.add('transition');
requestAnimationFrame(function() {
elem.style.left = '0px';
});
#container {
position: relative;
width: 400px;
height: 200px;
background-color: red;
}
#elem {
width: 50px;
height: 50px;
position: relative;
left: 0;
top: 0;
background-color: blue;
}
.transition.linear.scritta {
-webkit-transition: all 1.0s linear;
-moz-transition: all 1.0s linear;
-ms-transition: all 1.0s linear;
-o-transition: all 1.0s linear;
transition: all 1.0s linear;
}
<div id="container">
<div id="elem" class="transition linear scritta"></div>
</div>
Alternatively, forcing an update using getComputedStyle
appears to be effective as well.
getComputedStyle(elem).transitionDuration; // force update
var elem = document.getElementById('elem');
elem.classList.remove('transition');
elem.style.left = '200px';
elem.classList.add('transition');
getComputedStyle(elem).transitionDuration; // force update
elem.style.left = '0px';
#container {
position: relative;
width: 400px;
height: 200px;
background-color: red;
}
#elem {
width: 50px;
height: 50px;
position: relative;
left: 0;
top: 0;
background-color: blue;
}
.transition.linear.scritta {
-webkit-transition: all 1.0s linear;
-moz-transition: all 1.0s linear;
-ms-transition: all 1.0s linear;
-o-transition: all 1.0s linear;
transition: all 1.0s linear;
}
<div id="container">
<div id="elem" class="transition linear scritta"></div>
</div>