0

There is this progress bar that I am trying to control from javascript. In its demo it has this pretty nice flow, however if I try to set its width with javascript jquery $($0).css({'width': '80%'}), it looses its animation.

.progress-bar {
    margin: 0 auto;
    width: 100%;
    height: 10px;
    background-color: #e5e9eb;
}

.progress-bar .progress {
    position: relative;
    background-color: #90ee90;
    height: 10px;
    width: 100%;
    -webkit-animation-duration: 5s;
    -webkit-animation-name: width;
}

.progress-bar .progress .progress-shadow {
    background-image: linear-gradient(to bottom, #eaecee, transparent);
    position: absolute;
    height: 4em;
    width: 100%;
    top: 100%;
    transform: skew(-22.5deg);
    transform-origin: 0 0;
}

@-webkit-keyframes width {
    0%, 100% {
        transition-timing-function: cubic-bezier(1, 0, 0.65, 0.85);
    }

    0% {
        width: 0;
    }

    100% {
        width: 100%;
    }
  }

How can I control its width without losing its animation?

https://jsfiddle.net/u2c8ft0k/

8
  • 1
    So when you click on the button, it should progressively scroll back to that value? Commented Nov 13, 2017 at 2:22
  • I think you have to change the width of progress-bar instead jsfiddle.net/u2c8ft0k/1 Commented Nov 13, 2017 at 2:26
  • Do you want to rollback to 80% or start again from 0 to 80? Commented Nov 13, 2017 at 2:38
  • No, I don't want it to progressively scroll back and snap to the value. I want it to animate to the value so that in the end, I can control its % with javascript. @AliSheikhpour If my fiddle, if you click on button before its initial animation ends, it wont do it. so wait first for it to finish, then click btn. you will see, it will snap instantly to the position rather than using smooth transition animation Commented Nov 13, 2017 at 2:39
  • Why do you use animation? It's a transition that you want, isn't it? Commented Nov 13, 2017 at 2:50

4 Answers 4

3

What you want is a transition, not an animation, so don't use animation but transition.

var i = 1;
$('#change').click(function() {
  if (i == 1) {
    $('.progress').css('width', '80%');
  } else {
    $('.progress').css('width', '30%');
  }

  i == 1 ? i++ : i--

});
.progress-bar {
  margin: 0 auto;
  width: 100%;
  height: 10px;
  background-color: #e5e9eb;
}

.progress-bar .progress {
  position: relative;
  background-color: #90ee90;
  height: 10px;
  width: 0%;
  transition: width 5s cubic-bezier(1, 0, 0.65, 0.85);
}

.progress-bar .progress .progress-shadow {
  background-image: linear-gradient(to bottom, #eaecee, transparent);
  position: absolute;
  height: 4em;
  width: 100%;
  top: 100%;
  transform: skew(-22.5deg);
  transform-origin: 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="container text-center">
  <div class="progress-bar">
    <div class="progress">
      <div class="progress-shadow"></div>
    </div>
  </div>
</section>

<br /><br /><br /><br /><br /><br />
<button id="change">Change Width</button>

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

Comments

1

Something like this?

$('#change-0').click(function() {
	  $('.progress').css('width', '0%');
});
$('#change-50').click(function() {
  	$('.progress').css('width', '50%');
});
$('#change-100').click(function() {
  	$('.progress').css('width', '100%');
});
.progress-bar {
    margin: 0 auto;
    width: 100%;
    height: 10px;
    background-color: #e5e9eb;
}
.progress {
    position: relative;
    background-color: #90ee90;
    height: 10px;
    width: 0%;
    transition: width 2s;
}
.progress-shadow {
    background-image: linear-gradient(to bottom, #eaecee, transparent);
    position: absolute;
    height: 4em;
    width: 100%;
    top: 100%;
    transform: skew(-22.5deg);
    transform-origin: 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="container text-center">
  <div class="progress-bar">
    <div class="progress">
      <div class="progress-shadow"></div>
    </div>
  </div>
</section>
<br /><br /><br /><br />
<button id="change-0">0%</button>
<button id="change-50">50%</button>
<button id="change-100">100%</button>

Comments

0

There's got to be a better way of achieving it, but if you only need to switch between 80% and 30%, this does the trick.

var i = 1;
$('#change').click(function() {
	if (i == 1) {
    $('.progress-bar .progress').css('-webkit-animation-duration', 'initial'); 
    $('.progress-bar .progress').css('-webkit-animation-name', 'initial'); 

    $('.progress-bar .progress').css('-webkit-animation-duration', '1s'); 
    $('.progress-bar .progress').css('-webkit-animation-name', 'widthEighty'); 

   
    $('.progress').css('width', '80%');
  } else {
  $('.progress-bar .progress').css('-webkit-animation-duration', 'initial'); 
    $('.progress-bar .progress').css('-webkit-animation-name', 'initial'); 

    $('.progress-bar .progress').css('-webkit-animation-duration', '1s'); 
    $('.progress-bar .progress').css('-webkit-animation-name', 'widthThirty'); 

  	$('.progress').css('width', '30%');
  }
  
  i == 1 ? i++ : i--
	
});
.progress-bar {
    margin: 0 auto;
    width: 100%;
    height: 10px;
    background-color: #e5e9eb;
}

.progress-bar .progress {
    position: relative;
    background-color: #90ee90;
    height: 10px;
    width: 100%;
    -webkit-animation-duration: 1s;
    -webkit-animation-name: width;
}

.progress-bar .progress .progress-shadow {
    background-image: linear-gradient(to bottom, #eaecee, transparent);
    position: absolute;
    height: 4em;
    width: 100%;
    top: 100%;
    transform: skew(-22.5deg);
    transform-origin: 0 0;
}

@-webkit-keyframes width {
    0%, 100% {
        transition-timing-function: cubic-bezier(1, 0, 0.65, 0.85);
    }

    0% {
        width: 0;
    }

    100% {
        width: 100%;
    }
}

@-webkit-keyframes widthEighty {
    0%, 100% {
        transition-timing-function: cubic-bezier(1, 0, 0.65, 0.85);
    }

    0% {
        width: 30%;
    }

    100% {
        width: 80%;
    }
}

@-webkit-keyframes widthThirty {
    0%, 100% {
        transition-timing-function: cubic-bezier(1, 0, 0.65, 0.85);
    }

    0% {
        width: 80%;
    }

    100% {
        width: 30%;
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="container text-center">
  <div class="progress-bar">
    <div class="progress">
      <div class="progress-shadow"></div>
    </div>
  </div>
</section>

<br /><br /><br /><br /><br /><br />
<button id="change">Change Width</button>

3 Comments

But in your example, I can't set its milestones with javascript. This is instead starting every time from 0, rather than where it was. The use-case I want to achieve is: giving it milestones 10%, 40%, 80%, 100%, so that I can visually make user see the progress as it goes on
I changed it so that it goes from 30% to 80% Changing the width of only one css animation would be cleaner, but worst case scenario you could have 4 animations going from 0 to 10, 10 to 40, 40 to 80 and 80 to 100.
Alright. I see what you mean. This solves the problem (setting up keyframe for each scenario), but I am wondering if there is a better way to control it with % from javascript
0

You can use Animate API (https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) and control the transitions using Javascript. Check out the JSFiddle in the link or run from the attached code snippet to see if that is what you expect.

https://jsfiddle.net/xfct4rpx/2/

var i = 1;

var progress = document.getElementsByClassName("progress")[0];

$('#change').click(function() {
	if (i == 1) {
    progress.animate([{width: "0%"}, {width: "30%"}], {duration: 5000, easing: "cubic-bezier(1, 0, 0.65, 0.85)"})
    setTimeout(() => {progress.style.width = "30%"}, 5000)
	  //$('.progress').css('width', '30%');
  } else {
    progress.animate([{width: "30%"}, {width: "80%"}], {duration: 5000, easing: "cubic-bezier(1, 0, 0.65, 0.85)"})
    setTimeout(() => {progress.style.width = "80%"}, 5000)
  	//$('.progress').css('width', '30%');
  }
  
  i == 1 ? i++ : i--
	
});
.progress-bar {
    margin: 0 auto;
    height: 10px;
    background-color: #e5e9eb;
}

.progress {
    position: relative;
    background-color: #90ee90;
    height: 10px;
    width: 0%;
}

.progress-shadow {
    background-image: linear-gradient(to bottom, #eaecee, transparent);
    position: absolute;
    height: 4em;
    top: 100%;
    width: 100%;
    transform: skew(-22.5deg);
    transform-origin: 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="container text-center">
  <div class="progress-bar">
    <div class="progress">
      <div class="progress-shadow"></div>
    </div>
  </div>
</section>

<br /><br /><br /><br /><br /><br />
<button id="change">Change Width</button>

2 Comments

This is starting from 0 each time. I want to give it milestones instead with javascript 10%, 30%, 80%, 100%.
I just updated the snippet, check if that is what you are looking at, On first click the slider goes from 0%-30% on second click it goes from 30%-80%. If you don't want the first animation to 100%, just remove the animation you setup in the CSS file.

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.