Search code examples
javascriptcssanimationcss-animationssetinterval

changing the width of a div with setinterval


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.


Solution

  • 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>