Search code examples
javascripthtmlcssanimationmove

Javascript Change position of a div and after apply an animation


I have a div in the middle of the page.
I want to change position of my div in the top-right of the parent element(whithout animation), and after move to the top-left of the parent element with an animation.
So, in first time i used this code:
But this doesn't work properly.

function doAnimation(){
  var child = document.getElementById("child");
  var parent = document.getElementById("parent");
  
  child.style.left = parent.offsetWidth + "px";
  child.classList.add("child-animation");
  child.style.left = 0 + "px";
}
#parent{
  position: relative;
  width: 500px;
  height: 200px;
  background-color: red;
}

#child{
  position: absolute;
  width: 50px;
  height: 50px;
  top: 0;
  left: 225px;
  background-color: yellow;
}

#button{
  position: absolute;
  width: 100%;
  height: 30px;
  bottom: 0;
  background-color: grey;
}
  

.child-animation{
    -webkit-transition: all 700ms cubic-bezier(1,.01,.96,.87);
	-moz-transition: all 700ms cubic-bezier(1,.01,.96,.87);
	-ms-transition: all 700ms cubic-bezier(1,.01,.96,.87);
	-o-transition: all 700ms cubic-bezier(1,.01,.96,.87);
	transition: all 700ms cubic-bezier(1,.01,.96,.87);
}
<div id="parent">
  <div id="child">
  </div>
  <div id="button" onclick="doAnimation();">
  </div>
</div>

After i do this:

And this work?

function doAnimation () {
  var child = document.getElementById("child");
  var parent = document.getElementById("parent");
  
  child.style.left = parent.offsetWidth + "px";
  setTimeout( function () {
      child.classList.add("child-animation");
      child.style.left = 0 + "px";
   }, 0);
}
#parent{
  position: relative;
  width: 500px;
  height: 200px;
  background-color: red;
}

#child{
  position: absolute;
  width: 50px;
  height: 50px;
  top: 0;
  left: 225px;
  background-color: yellow;
}

#button{
  position: absolute;
  width: 100%;
  height: 30px;
  bottom: 0;
  background-color: grey;
}
  

.child-animation{
    -webkit-transition: all 700ms cubic-bezier(1,.01,.96,.87);
	-moz-transition: all 700ms cubic-bezier(1,.01,.96,.87);
	-ms-transition: all 700ms cubic-bezier(1,.01,.96,.87);
	-o-transition: all 700ms cubic-bezier(1,.01,.96,.87);
	transition: all 700ms cubic-bezier(1,.01,.96,.87);
}
<div id="parent">
  <div id="child">
  </div>
  <div id="button" onclick="doAnimation();">
  </div>
</div>


My question is, WHY the first code doesn't work and the second with setTimeout(function,0) work?

Help me, please!


Solution

  • A forced redraw is required

    You'll need to read a property that makes browsers recalculate the element. Like this:

    child.style.left = parent.offsetWidth + "px";
    var forced=child.scrollLeft; // Forces a redraw
    child.classList.add("child-animation");
    child.style.left = 0 + "px";
    

    This is due to how browsers group up property changes and run them all at once during the next redraw event. In the first case:

    child.style.left = parent.offsetWidth + "px";
    child.classList.add("child-animation");
    child.style.left = 0 + "px";
    

    All essentially runs at the same time, meaning the browser acts like it actually received only this:

    child.classList.add("child-animation");
    child.style.left = 0 + "px";
    

    Not all browsers batch (group up) properties like this, so that's why it varies from browser to browser.