0

I want to create a css transition and it is important, that I can "reset" the width of my "box" in advance, each time my function is called.

By just setting the width of the box to zero, the element shrinks with animation. But I want to reset without animation. So I created a class which disables and enables the effect before and after resetting. Unfortunately this doesn't work. I guess because JavaScript is asynchronous and it just flys over the width=0 command. I figured out, that if I interrupt the runtime with an alert before removing the "notransition" it works, but of course this is not a valid way.

I always wanted to have a solution for this async problem. I would be very happy for a explanation and solution for my attempt and maybe an even better solution for the resetting. Thank you!

function test() {

            var duration = 5;

            document.getElementById("box").classList.add('notransition');
            document.getElementById("box").style.width = 0 + "%"
            document.getElementById("box").classList.remove('notransition');

            //Fill progress bar
            document.getElementById("box").style.setProperty('transition-duration', duration + 's');
            document.getElementById("box").style.width = 100 + "%"

            setTimeout(function () {
                console.log("Progress finished")
            }, duration * 1000);

        }
    * {
        box-sizing: border-box;
    }

    html {
        padding: 0;
        margin: 0;
        width: 100%;
    }

    body {
        margin: 0;
        width: 100%;
        padding: 20px;
    }

    #box {
        border: 1px solid red;
        height: 20px;
        width: 10%;
        background-color: rgba(219, 72, 72, 0.3);
        transition-property: width;
        transition-duration: 0s;
        transition-timing-function: linear;
    }

    .notransition {
        -webkit-transition: none !important;
        -moz-transition: none !important;
        -o-transition: none !important;
        transition: none !important;
    }
<div id="box" onclick="test()"></div>

1 Answer 1

1

Using two classes to toggle between, specifically for the transition-delay property, it works quite fine. You also have to allow a small delay to have the with restored to 10% before the animation starts.

function test() {

  // "normal" transition delay is zero seconds
  let box = document.getElementById("box");
  box.style.width = "10%";

  // Allow a small delay (10ms) for the width to update on screen
  setTimeout(function() {

    // Change the transition delay and the width
    box.classList.remove('normal');
    box.classList.add('transitionning');
    box.style.width = "100%";

    // When completed, restore the "normal" transition delay
    setTimeout(function() {
      console.log("Progress finished")
      box.classList.remove('transitionning');
      box.classList.add('normal');
    }, 5000);
  }, 10)
}
* {
  box-sizing: border-box;
}

html {
  padding: 0;
  margin: 0;
  width: 100%;
}

body {
  margin: 0;
  width: 100%;
  padding: 20px;
}

#box {
  border: 1px solid red;
  height: 20px;
  width: 10%;
  background-color: rgba(219, 72, 72, 0.3);
  transition-property: width;
  transition-timing-function: linear;
}

.normal {
  transition-duration: 0s;
}

.transitionning {
  transition-duration: 5s;
}
<div id="box" class="normal" onclick="test()"></div>

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

5 Comments

Thank you, that works so far. But we are loosing 10ms of runtime, which can be critical in a different application. Isn't there something, like a Promise, which tells the programm when changing of the width is done?
I don't think so... By the way, did you try with 1ms?
It also seems to works with 1ms, but isn't it kind of a random behaviour ? Does it depent on hardware/ browser/ operation system? 0ms didn't work for me.
I have to correct myself. I did a couple of changes in the rest of my project which probably has changed the overall runtimes of the chain of functions and now 1ms isn't enough. It stopped working. If I increase the timeout to 10ms it works again. So we have a very unstable solution for the problem because it depends on serval other things around the function.
That is about the best you can do with DOM elements. But, for sure, there are other ways like animating a SVG with a GSAP timeline. That is someting else.

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.