nandwana92
nandwana92

Reputation: 105

How to set 0% css of keyframes as current css value for the element?

I am trying to make a progress indicator div using CSS animations. Please refer to the linked JSBin. The behavior I am trying to achieve is, when the user clicks on stage3 after stage1, the div width should increase from current 30% to 100% and not start from 0% as it is doing right now. I know if i set the 0% value as width: 30%, I can get that. But it won't work so well if I have many stages. I want the animation to start from final width of last stage to the width specified in new stage.

Progress indicator snippet

document.getElementById('stage1').addEventListener('click', function() {
  document.getElementById('progress').classList.add('stage1');
}, false);

document.getElementById('stage2').addEventListener('click', function() {
  document.getElementById('progress').classList.add('stage2');
}, false);

document.getElementById('stage3').addEventListener('click', function() {
  document.getElementById('progress').classList.add('stage3');
}, false);
.progress-wrapper {
  height: 10px;
  width: 400px;
  background-color: #BBDEFB;
}
#progress {
  background-color: #AADE00;
  height: 10px;
  width: 0;
}
.stage1 {
  animation-name: stage1;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes stage1 {
  to {
    width: 30%;
  }
}
.stage2 {
  animation-name: stage2;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes stage2 {
  to {
    width: 70%;
  }
}
.stage3 {
  animation-name: stage3;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes stage3 {
  to {
    width: 100%;
  }
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>

<body>
  <div class="progress-wrapper">
    <div id="progress"></div>
  </div>
  <pre>
    
  </pre>
  <button id="stage1">stage1</button>
  <button id="stage2">stage2</button>
  <button id="stage3">stage3</button>
</body>

</html>

Upvotes: 4

Views: 1412

Answers (2)

Gull Noor
Gull Noor

Reputation: 1

you can use custom CSS variable:

  1. create custom variable in css e.g

element{ --temp_variable: 0; }

  1. get current property value in JavaScript and assign to custom variable e.g. if you need color value of element <p> :

element = querySelector("p");  //or any other selector
computed_element = getComputedStyle(element);
current_color = computed_element.getPropertyValue("color")
computed_element.setProperty("--temp_variable",current_color);

  1. use that variable in CSS keyframe e.g.

@keyframe{
0%{ color: var(--temp_variable) }
100% { ..... }
}

Upvotes: 0

Josh Crozier
Josh Crozier

Reputation: 240928

I'm not aware of a CSS-only solution, but you could set the width of the progress element before adding the class.

In doing so, it will transition from the previous width rather than from 0.

var progress = document.getElementById('progress');

document.getElementById('stage1').addEventListener('click', function() {
  setPreviousWidth();
  progress.classList.add('stage1');
}, false);

document.getElementById('stage2').addEventListener('click', function() {
  setPreviousWidth();
  progress.classList.add('stage2');
}, false);

document.getElementById('stage3').addEventListener('click', function() {
  setPreviousWidth();
  progress.classList.add('stage3');
}, false);

function setPreviousWidth () {
  progress.style.width = progress.offsetWidth + 'px';
}
.progress-wrapper {
  height: 10px;
  width: 400px;
  background-color: #BBDEFB;
}
#progress {
  background-color: #AADE00;
  height: 10px;
  width: 0;
}
.stage1 {
  animation-name: stage1;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes stage1 {
  to {
    width: 30%;
  }
}
.stage2 {
  animation-name: stage2;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes stage2 {
  to {
    width: 70%;
  }
}
.stage3 {
  animation-name: stage3;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes stage3 {
  to {
    width: 100%;
  }
}
<div class="progress-wrapper">
  <div id="progress"></div>
</div>
<pre>
    
  </pre>
<button id="stage1">stage1</button>
<button id="stage2">stage2</button>
<button id="stage3">stage3</button>

Upvotes: 3

Related Questions