Home > Mobile >  automatic css animation duration based on unknown width
automatic css animation duration based on unknown width

Time:09-13

I have a css marquee with scrolling text. the length of the text is unknown before the page is loaded, because it's random. My css animation awkwardly speeds up and slows down the animation based on how long it is and I cant figure out a workaround. All im looking for is a consistent scroll speed no matter how long or short the width of the object is, but I literally can't figure it out. if it helps, here's a code pen

and here's the code i have:

fetch("https://raw.githubusercontent.com/cupofdirtfordinner/mesacomplex2.0/main/roots/js/json/lines.json")
  .then(res => res.json())
  .then(json => {
    document.getElementById("splash").innerHTML = json[Math.floor(Math.random() * json.length)];
  }).catch(error => {
    console.log(error);
  });
body {
  background-color: black;
}

div {
  height: 50px;
  overflow: hidden;
  position: relative;
  white-space: nowrap;
}

div p {
  font-size: 2em;
  color: rgba(255, 255, 255, 0.6);
  position: absolute;
  margin: 0;
  text-align: center;
  transform: translateX(100%);
  animation: cssmarquee linear infinite;
  /*width: auto;
    animation-duration:calc(var(width)); <- what im trying to do*/
  animation-duration: 5s;       /* <- what works*/
}

@keyframes cssmarquee {
  0% {
    transform: translateX(100%);
  }
  100% {
    transform: translateX(-100%);
  }
}
<div>
  <p id="splash"></p>
</div>

CodePudding user response:

Just a thought. Maybe you could measure the length of the text container, determine the proper speed, then apply it to the HTML element...?

...
.then(json => {
    let sp = document.getElementById("splash")
    sp.innerHTML = json[Math.floor(Math.random() * json.length)];
    ///assuming the element is not a block level (display:inline-block)
    let speed = parseInt(sp.offsetWidth) * .4; // making up numbers here
    sp.style.animationDuration = `${speed}s`
})...

CodePudding user response:

You can measure the text width with clientWidth and dynamically add the animation-duration according to that width.

setInterval(10)
fetch("https://raw.githubusercontent.com/cupofdirtfordinner/mesacomplex2.0/main/roots/js/json/lines.json")
.then(res => res.json())
.then(json => {
    const splash = document.getElementById("splash")
    splash.innerHTML = json[Math.floor(Math.random() * json.length)];
    splash.style.animationDuration = `${Math.round(splash.clientWidth / 200)}s`
}).catch(error => {
    console.log(error);
});
body {background-color:black;}
div {
    height: 50px;
    overflow: hidden;
    position: relative;
    white-space: nowrap;
    }

    div p {
    font-size: 2em;
    color: rgba(255,255,255,0.6);
    position: absolute;
    margin: 0;
    text-align: center;
    transform:translateX(100%);
    animation: cssmarquee linear infinite;
    
    /*width: auto;
    animation-duration:calc(var(width)); <- what im trying to do*/
      animation-duration: 5s; /* <- what works*/
    
    }
    @keyframes cssmarquee {
    0% {
    transform: translateX(100%);
    }
    100% {
    transform: translateX(-100%);
    }
    }
<div>
<p id="splash"></p>
</div>

  • Related