mvovchak
mvovchak

Reputation: 291

CSS Keyframe animation breaks transition when both are applied on same property

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.

Upvotes: 2

Views: 2727

Answers (1)

Harry
Harry

Reputation: 89750

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>

Upvotes: 4

Related Questions