2

I want to do the following things:

  1. show a div element;
  2. move it to a an initial position;
  3. set transition properties;
  4. move it to the target position using CSS transition.

A minimal example:

function bla() {
  /*
    var obj = $('#box');
    obj.css("left", "200px");
    obj.css("display", "initial");
    obj.addClass("trans");
    obj.css("left", "500px");
  */

  var elem = document.getElementById('box');
  elem.style.left = "200px";
  elem.style.display = "initial";
  elem.className = "box trans";
  elem.style.left = "500px";
}
#btn {
  position: fixed;
  top: 60px;
  left: 0px;
  width: 50px;
  height: 50px;
  background-color: #FEDCBA;
}
.box {
  display: none;
  position: fixed;
  top: 0px;
  left: 0px;
  width: 50px;
  height: 50px;
  background-color: #ABCDEF;
}
.box.trans {
  -webkit-transition: left 2s;
  -moz-transition: left 2s;
  transition: left 2s;
}
<div id="box" class="box"></div>
<div id="btn" onclick="bla()">click here</div>

JSFiddle.

It does not work at all. What is wrong?

If I set the element initially visible, I get a smooth transition starting from the origin left:0 which is totally strange because I assign elem.style.left = "200px"; before I actually add the transition properties...

2
  • If you're using CSS transforms, wouldn't it be easier to stick your new styles in a class and simply add that class? Commented Feb 10, 2017 at 15:53
  • Unfortunately i can't because i have to calulate the position. Commented Feb 10, 2017 at 16:01

4 Answers 4

2

You should avoid using style in javascript, just switch class years put all your animation in your css file.

You can't put transition together with display: none;, you have to use opacity: 0; instead.

function bla()
{
	var obj = $('#box');
	obj.toggleClass("trans");
}
#btn
{
  position:fixed;
  top:60px;
  left:0px;
  width:50px;
  height:50px;
  background-color:#FEDCBA;
}

.box
{
  opacity: 0;
  position:fixed;
  top:0px;
  left:0px;
  width:50px;
  height:50px;
  background-color:#ABCDEF;
  -webkit-transition: transform  2s,opacity  2s;
  transition: transform  2s,opacity  2s;
}

.box.trans
{
  opacity: 1;
  -ms-transform: translate(500px,0); /* IE 9 */
  -webkit-transform: translate(500px,0); /* Safari */
  transform: translate(500px,0);
	
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box" class="box">
</div>
<div id="btn" onclick="bla()">
click here
</div>

Sign up to request clarification or add additional context in comments.

Comments

2

DOM changes don't take effect until they can be rendered. Javascript is single-threaded (meaning you cannot run two pieces of code simultaneously), and run on the same thread as the render cycle.

Because of this, the renderer cannot fire unless you give it time to look at the new state of the DOM by deferring execution of your JS code (using setTimeout or requestAnimationFrame). So unless you give the browser time to render, only the final value before the renderer gets to look at the DOM is what matters.

This answer to a previous question goes over the exceptions to the rule.

Here's an updated version of your jsfidde that uses requestAnimationFrame to get around the issue.

1 Comment

After 2 hours of searching and groaning, THIS was the comment that saved my sanity. Thank you.
1

I can not explain why. Maybe someone could, I'd be curious too, but with a time-out works.

setTimeout(function(){
    elem.style.left = "500px";
},1);

It is probably too fast assigning properties left 500 and the transition to record the old location 200?

https://jsfiddle.net/StepBaro/s82rj48q/2/

2 Comments

Yes i thought about that it could be a timing thing.. but it does not make sense because this would violate the order of the calls. When i set the position to 200 then it should set the position. It must not wait with the change after the next instructions..
Evidently the instructions running simultaneously. I tried to replace the timeout with a very long for loop, and does not work, I think it not refresh the dom, I do not know if you have other solutions. Or jquery, but it is the same logic jsfiddle.net/StepBaro/s82rj48q/9
0

It's because you have the div hidden, so it first need to display it and then add the transition, that is why it needs the delay.

3 Comments

Yeah that's why i call elem.style.display = "initial"; first to display it. I even change its position after i displayed it.
Yes, but you are doing both things at the same time
You could bind the animation to the display change. Once you display it then launch the animation. But you definitely need to first display it, otherwise it will do both things at the same time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.