2

I've got a strange behavior when adding a CSS animation on top of the transition for a progress bar element: the transition just stops executing. Not sure why I cannot have both, an initial animation and the transition when changing the element's width.

The whole thing looks like this:

HTML:

  <div class="container">
    <div class="bar"></div>
    <div class="actions">
      <button id="btnResize">Resize bar</button>
    </div>
  </div>

CSS:

.bar {
  height: 3px;
  width: 300px;
  background-color: blue;
  position: absolute;
  transition: margin-left 0.5s ease-in-out, width 0.5s ease-in-out;
  /*Transition breaks when I add the line below with animation rule*/
  animation: progress-bar 1s 0.2s ease both;
}

@keyframes progress-bar {
  0% {
    width: 0
  }
}

I have also created a JSBin to show the weirdness (https://jsbin.com/sufofitiri/edit?html,css,output)

Hopefully someone can give me a clue.

Harry
  • 87,580
  • 25
  • 202
  • 214
mvovchak
  • 291
  • 5
  • 13
  • Yoyu can not set a transition and an animation on the same property at the same time – vals Nov 10 '15 at 17:59
  • 1
    @vals is correct but you can use `max-width` like in [this sample](https://jsbin.com/linicajidi/1/edit?html,css,js,output) as an alternate. I will add it as answer if it solves your problem. – Harry Nov 11 '15 at 08:40
  • @Harry, it actually does solve it! Not sure why though, I was about to go with a JS solution, but this is much easier. Thanks! – mvovchak Nov 11 '15 at 14:08

1 Answers1

4

For some reason, it seems like setting animation and transition on the same property causes it to not work. This Bugzilla thread kind of confirms this statement (that, animation takes full control over the property and prevents the transition from having any effect).

So, the alternate would be to use width for one and max-width for the other. The choice of which one should be used for animation and which should be used for transition is up to us, there is no fixed rule for it.

Since your element already has a fixed width, setting the same width as the max-width should not cause any trouble. In the below snippet, width is used for animation and max-width is used for the transition.

(function() {
  function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  $("#btnResize").on("click", function() {
    $(".bar").css({
      "max-width": getRandomInt(1, 300) + "px"
    });
  });
})();
.container {
  width: 100%;
  position: relative;
  margin: 1em;
}
.bar {
  height: 3px;
  background-color: blue;
  position: absolute;
  transition: margin-left 0.5s ease-in-out, max-width 0.5s ease-in-out;
  animation: progress-bar 1s 0.2s ease both;
}
.actions {
  padding-top: 30px;
}
@keyframes progress-bar {
  0% {
    width: 0
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="bar" style="width: 300px; max-width: 300px"></div>
  <div class="actions">
    <button id="btnResize">Resize</button>
  </div>
</div>

In the below snippet, max-width is used for animation and width is used for transition. Both will work as expected.

(function() {
  function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  $("#btnResize").on("click", function() {
    $(".bar").css({
      "width": getRandomInt(1, 300) + "px"
    });
  });
})();
.container {
  width: 100%;
  position: relative;
  margin: 1em;
}
.bar {
  height: 3px;
  background-color: blue;
  position: absolute;
  transition: margin-left 0.5s ease-in-out, width 0.5s ease-in-out;
  animation: progress-bar 1s 0.2s ease both;
}
.actions {
  padding-top: 30px;
}
@keyframes progress-bar {
  0% {
    max-width: 0
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="bar" style="width: 300px; max-width: 300px"></div>
  <div class="actions">
    <button id="btnResize">Resize</button>
  </div>
</div>
Harry
  • 87,580
  • 25
  • 202
  • 214