jquery – Final application time of CSS properties

Question:

I found that some CSS properties (I think primarily those responsible for positioning and displaying elements) are applied with a slight delay (often breaking the code).

In my case, this is the opacity property when creating a slideshow. I simplified the example as much as possible, removed the classes and everything unnecessary in order to minimize the code.

The next function makes the element disappear (instantly) and then reappear (smoothly).

function fadeIn() {
    var $el=$('div');
    $el.css('transition', '').css('opacity', '0').delay(13)
    .queue(function(next) {
        $(this).css('transition', 'all 2s').css('opacity', '1');
        next(); 
    });
}

Everything works, but delay (13) looks like a dirty hack (in chrome, delay (0) is enough, but in Firefox you need at least 13). And on a slower PC, will you need to set the delay even more?

I think the following is happening: if the delay is not large enough, the opacity application does not have time to occur – and the transition is immediately applied (and you can put a cross on the instant disappearance).

Is there a beautiful solution to the problem? to execute certain code only after the CSS properties are "really" applied to the elements?

Answer:

When you try to change styles, the browser optimizes the recalculation as much as possible, and it is highly likely that a set of sequential actions will be applied at one time.

In order to force the browser to force the changes, you need to get the value of the width or height of the element.

Here's an example: https://jsfiddle.net/whpmhwzz/4/

~function () {
  var demo = document.getElementById("demo");

  document.getElementById("to-0").addEventListener("click", function() {
    demo.style.width = 0;
  });

  document.getElementById("to-100").addEventListener("click", function() {
    demo.style.width = "100%";
  });

  document.getElementById("try-force-to-0").addEventListener("click", function() {
    demo.style.transition = "none";
    demo.style.width = "0";
    demo.style.transition = ""; // IE fails to assign null
  });

  document.getElementById("force-to-0").addEventListener("click", function() {
    demo.style.transition = "none";
    demo.style.width = "0";
    getComputedStyle(demo).transition; // No recalculation in FF and IE
    demo.style.transition = "";
  });

  document.getElementById("force-to-0-again").addEventListener("click", function() {
    demo.style.transition = "none";
    demo.style.width = "0";
    getComputedStyle(demo).width;
    demo.style.transition = "";
  });

  document.getElementById("force-to-0-height").addEventListener("click", function() {
    demo.style.transition = "none";
    demo.style.width = "0";
    getComputedStyle(demo).height;
    demo.style.transition = "";
  });

  document.getElementById("force-to-0-fail").addEventListener("click", function() {
    demo.style.transition = "none";
    demo.style.width = "0";
    getComputedStyle(demo); // No recalculation
    demo.style.transition = "";
  });
}();
p {
  margin-top: 60px;
}
div {
  width: 100%;
  transition: width 3s linear;
  height: 2em;
  background: red;
}
<p>
  <button id=to-0>To 0</button>
  <button id=try-force-to-0>Try force to 0</button>
  <button id=force-to-0>Force to 0</button>
  <button id=force-to-0-again>Force to 0 again</button>
  <button id=force-to-0-height>Force to 0 once more</button>
  <button id=force-to-0-fail>Force to 0 fail</button>
  <button id=to-100>To 100</button>
</p>
<div id=demo></div>
Scroll to Top