skip to Main Content

I have this code with css animation:

@keyframes progress-bar {
  0% {
    width: 0;
  }
  50% {
    width: 100%;
  }
  100% {
    width: 0;
  }
}

.box {
  position: relative;
  height: 3px;
  margin-top: 20px;
  background: transparent;
}

.line {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 100%;
  background: red;
  -webkit-animation: progress-bar 6s ease-in infinite alternate forwards;
  animation: progress-bar 6s ease-in infinite alternate forwards;
}
<div class="box">
  <div class="line"></div>
</div>

This is an example link to codesandbox: link

This allows me to fill in endlessly div.line in three seconds and then hide it’s width back in three seconds.

I want to implement in Vanila JS the same functionality with using setInterval. I understand that I need to use setInterval, loop and get the width using the clientwidth. But all my attempts either immediately clear setInterval or doesn’t work.
Please help me find the optimal solution, thank you.

2

Answers


  1. Here is a JS version – we still need SOME CSS

    I just SET the width and use a couple of ternaries to increment of decrement it

    const line = document.querySelector('.line');
    let width = 0;
    let growing = true;
    const intervalDuration = 30; 
    const totalDuration = 6000; // total duration of the animation in milliseconds
    const maxSteps = totalDuration / intervalDuration; // number of steps in the animation cycle
    const interval = setInterval(() => {
      // Increment or decrement the width based on the growing state
      width += growing ? 100 / maxSteps : -100 / maxSteps;
    
      // Switch direction if limits are reached
      growing = (growing && width >= 100) || (!growing && width <= 0) ? !growing : growing;
    
      line.style.width = `${width}%`; 
    }, intervalDuration);
    .box {
      position: relative;
      height: 3px;
      margin-top: 20px;
      background: transparent;
    }
    
    .line {
      position: absolute;
      top: 0;
      left: 0;
      width: 0;
      height: 100%;
      background: red;
    }
    <div class="box">
      <div class="line"></div>
    </div>
    Login or Signup to reply.
  2. You can also use another alternative with css variable and javascript as follow. If you want to reach 100% from 0% in 3s you need to set the interval to 30ms.

    const line = document.querySelector('.line')
    const root = document.querySelector(':root')
    let lineWidth = 0
    let increment = true
    
    
    function incrementWidth(){
        if(lineWidth<100 && increment){
            lineWidth+=1
            root.style.setProperty("--width", `${lineWidth}%`)
            if(lineWidth===100){ 
                increment=false
            }
        }
        if(lineWidth > 0 && !increment){
            lineWidth-=1
            root.style.setProperty("--width", `${lineWidth}%`)
            if(lineWidth===0){ increment=true}
        }
    }
    
    let interval_ID = setInterval(()=>{
        incrementWidth()
    },30)
      
      :root{
        --width: 0%;
      }
    
      .box {
        position: relative;
        height: 3px;
        margin-top: 20px;
        background: transparent;
      }
      
      .line {
        position: absolute;
        top: 0;
        left: 0;
        width: var(--width);
        height: 100%;
        background: red;
      }
        <div class="box">
            <div class="line"></div>
        </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search