javascripthtmlcsstimercountdown

How to prevent a Countdown timer to be jumpy/ pushing the number next to it using (HTML, CSS, JS only)


I am working on a project where countdown is the main focus. But when the count down starts as the numbers count down certain numbers push and pull other numbers like when eg. 22:00 changes it pulls the number on the right towards left eg. 21:59. This makes the countdown look jumpy and weird.

I want to avoid this behaviour. What I am thinking is that each number occupy a certain space and stay at its place fixed while the countdown. I don't want to use a monospace font for visual reasons.


let timeLeft = 25 * 60; // seconds
let timerInterval;

const timeLeftEl = document.getElementById('time-left');

// Function to start the timer
function startTimer() {
  timerInterval = setInterval(() => {
    timeLeft--;
    updateTimeLeftTextContent();
    if (timeLeft === 0) {
      clearInterval(timerInterval);
    }
  }, 1000);
}

// Function to update the time left text content
function updateTimeLeftTextContent() {
  const minutes = Math.floor(timeLeft / 60);
  const seconds = timeLeft % 60;
  timeLeftEl.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}

startTimer()
timer-container {
  position: relative;
  margin-top: 0.5rem;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: transparent;
  cursor: pointer;
  border: 2px solid transparent;
  border-radius: 50px;
  transition: border-color 0.2s ease-in-out;
  overflow: hidden;
  max-height: 180px;
  padding: 0px 20px;
}

#timer-container:hover {
  border-color: black;
}

#time-left {
  font-family: "Karla", sans-serif;
  font-size: 10.375rem;
  font-weight: 600;
  text-align: center;
  margin-bottom: 1rem;
  letter-spacing: -5px;
  user-select: none;
  position: relative;
  z-index: 1;
  opacity: 1;
}
<link href="https://fonts.googleapis.com/css2?family=Karla:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">

<div id="timer-container">
  <div id="time-left">25:00</div>
</div>


I am quite new to pure HTML, CSS, Javascript. So a breif explaination on this is possible is much appriciated.

I have tried to separate the timer into individual span tags '00', ':', '00' then tried to make block of fixed size but it just made it more werid. I also tired ch for the timer-container and the time-left but it didnt work.

I want the timer to stay in one place like monospace characters but the text is not monospace font, that what I want to solve


Solution

  • Some fonts provide alternate glyph styles, which seems to be the case for the Karla font you are using. You can use the font-variant-numeric CSS property to make it behave like a monospace font:

    font-variant-numeric: tabular-nums;
    

    let timeLeft = 25 * 60; // seconds
    const timeLeftEl = document.getElementById('time-left');
    
    (function loop() {
      updateTimeLeftTextContent();
      if (timeLeft > 0) {
        timeLeft -= 1;
        setTimeout(loop, 1000);
      }
    })();
    
    function updateTimeLeftTextContent() {
      const minutes = Math.floor(timeLeft / 60);
      const seconds = timeLeft % 60;
      timeLeftEl.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
    }
    #time-left {
      font-family: "Karla", sans-serif;
      font-size: 8rem;
      font-weight: 800;
      text-align: center;
      font-variant-numeric: tabular-nums; /* <------- */
    }
    <link href="https://fonts.googleapis.com/css2?family=Karla:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">
    
    <div id="time-left">25:00</div>