The transition does not work without requesting the width property

I want to animate the broadcast of X with the transition to the click event by adding a class to the div in js. Transformation and transition properties are added to the css file.

var widget = document.getElementById('widget'); widget.style.display = 'block'; document.getElementById('widget2').clientWidth; //comment this line out and it wont work widget.className = 'visible'; 

It only works if I request the width property of the any element in dom before adding the class.

here is jsfiddle: https://jsfiddle.net/5z9fLsr5/2/

Can someone explain why this is not working?

+6
source share
2 answers

This is because you start your transition and at the same time modify the display "property. Changing the display will result in the loss of any transition (admittedly necessary), so it would be nice to highlight the change and the actual transition display :

https://jsfiddle.net/5z9fLsr5/3/

 document.getElementById('showWidget').addEventListener('click', function(e) { e.preventDefault(); var widget = document.getElementById('widget'); widget.style.display = 'block'; //document.getElementById('widget2').clientWidth; window.setTimeout(function(){ widget.className = 'visible'; },0); }); 
 #widget { width: 200px; height: 80px; background: black; position: absolute; transition: transform 500ms; transform: translateX(-200px); display: none; } #widget.visible { transform: translateX(200px); } #widget2 { position: absolute; right: 0 } 
 <a href="#" id="showWidget">show</a> <div id="widget"></div> <div id="widget2">xxx</div> 

The clientWidth request seems to “pause” execution for some time, so it works too.

+2
source

The problem is the initial setup of display: none . In the browser layout manager, this means that the layout should be executed as if this element were not even in the DOM (this is all the same, mind you). This means that the CSS style is transform: translateX(-200px); will not apply.

Performing this action:

 widget.style.display = 'block'; widget.className = 'visible'; 

launches both modifications essentially at the same time - the layout is only redone after both operators are executed. Insert document.getElementById('widget2').clientWidth; ( clientHeight also works) launches the layout manager for redrawing, thereby registering transform: translateX(-200px) .

As mentioned above, the solution should either use opacity instead of display (this would be my choice) or use setTimeout with a delay of 0 (see Why is setTimeout (fn, 0) sometimes useful? ).

0
source

Source: https://habr.com/ru/post/987025/


All Articles