0

I notice that when I remove setTimeout from the code below, the animation stops working. Can someone explain to me what's happening under the hood?

Why is it necessary to insert this setTimeout here, even though the time value is 0? In my mind, it should execute right away, so why insert setTimeout(cb,0)?

setTimeout(() => {
... //see below for code
}, 0);


<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <style>
    .message-ball {
      font-size: 20px;
      line-height: 200px;
      text-align: center;
    }
    .circle {
      transition-property: width, height, margin-left, margin-top;
      transition-duration: 2s;
      position: fixed;
      transform: translateX(-50%) translateY(-50%);
      background-color: red;
      border-radius: 50%;
    }
  </style>
</head>

<body>

  <button onclick="go()">Click me</button>

  <script>

  function go() {
    showCircle(150, 150, 100, div => {
      div.classList.add('message-ball');
      div.append("Hello, world!");
    });
  }

  function showCircle(cx, cy, radius, callback) {
    let div = document.createElement('div');
    div.style.width = 0;
    div.style.height = 0;
    div.style.left = cx + 'px';
    div.style.top = cy + 'px';
    div.className = 'circle';
    document.body.append(div);

    setTimeout(() => {
      div.style.width = radius * 2 + 'px';
      div.style.height = radius * 2 + 'px';

      div.addEventListener('transitionend', function handler() {
        div.removeEventListener('transitionend', handler);
        callback(div);
      });
    }, 0);
  }
  </script>


</body>
</html>
guest
  • 2,185
  • 3
  • 23
  • 46
  • 2
    Check [this](https://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful) question –  Apr 04 '19 at 22:31
  • @charlietfl this is not a duplicate. the answer is addressed by Jonas Wilms below, which is more specific than the duplicate you described. – guest Apr 04 '19 at 22:43
  • The essential reasoning is the same – charlietfl Apr 04 '19 at 22:43
  • @charlietfl the question you introduced is more general, and this is a more specific example. – guest Apr 04 '19 at 22:44
  • The reasoning is not the same @charlietfl. In this piece of code, i'm making changes to `style.width` and `style.height`, and this is why I need the additional `setTimeout`, whereas the reasoning in the duplicate question, is a more general, non-specific, explanation, ie "browser cooperative multitasking", which is not the case here. – guest Apr 04 '19 at 22:46
  • Still comes down to browser needing time for inital render so while the other is a bit more general the explanation is well written and explains a little more what's happening under the hood so both do go together. Is not a negative having that other link here – charlietfl Apr 04 '19 at 22:54
  • @charlietfl OK got it! I thought this question is closed once a duplicate question is linked to this one, but it seems like it can still be found here. – guest Apr 04 '19 at 22:58

1 Answers1

2

Because transitions only happen when a property was changed. If you do

 div.style.width = 0;
 div style.width = "1000px";

That wil not animate anything as the property was directly changed. If you defer the second update, it will detect the change and cause a transition to happen.,

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151