JSFiddle - React, Tailwind, and code Playground

HTML

<div class="timer" data-time="01.10.2021 18:30">
    <div class="timer__items">
      <div class="timer__item timer__days">00</div>
      <div class="timer__item timer__hours">00</div>
      <div class="timer__item timer__minutes">00</div>
      <div class="timer__item timer__seconds">00</div>
    </div>
  </div>

CSS

*,
 *::before,
 *::after {
   box-sizing: border-box;
 }

body {
      margin: 0;
      font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
      font-size: 1rem;
      font-weight: 400;
      line-height: 1.5;
      color: #212529;
      background-color: #fff;
      -webkit-text-size-adjust: 100%;
      -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
      display: flex;
      justify-content: center;
    }

    .timer__items {
      display: flex;
      font-size: 48px;
    }

    .timer__item {
      position: relative;
      min-width: 60px;
      margin-left: 10px;
      margin-right: 10px;
      padding-bottom: 15px;
      text-align: center;
    }

    .timer__item::before {
      content: attr(data-title);
      display: block;
      position: absolute;
      left: 50%;
      bottom: 0;
      transform: translateX(-50%);
      font-size: 14px;
    }

    .timer__item:not(:last-child)::after {
      content: ':';
      position: absolute;
      right: -15px;
    }

JavaScript

document.addEventListener('DOMContentLoaded', function () {
      // конечная дата
      const deadline = new Date(2021, 10, 01, 18, 30);
      // id таймера
      let timerId = null;
      // склонение числительных
      function declensionNum(num, words) {
        return words[(num % 100 > 4 && num % 100 < 20) ? 2 : [2, 0, 1, 1, 1, 2][(num % 10 < 5) ? num % 10 : 5]];
      }
      // вычисляем разницу дат и устанавливаем оставшееся времени в качестве содержимого элементов
      function countdownTimer() {
        const diff = deadline - new Date();
        if (diff <= 0) {
          clearInterval(timerId);
        }
        const days = diff > 0 ? Math.floor(diff / 1000 / 60 / 60 / 24) : 0;
        const hours = diff > 0 ? Math.floor(diff / 1000 / 60 / 60) % 24 : 0;
        const minutes = diff > 0 ? Math.floor(diff / 1000 / 60) % 60 : 0;
        const seconds = diff > 0 ? Math.floor(diff / 1000) % 60 : 0;
        $days.textContent = days < 10 ? '0' + days : days;
        $hours.textContent = hours < 10 ? '0' + hours : hours;
        $minutes.textContent = minutes < 10 ? '0' + minutes : minutes;
        $seconds.textContent = seconds < 10 ? '0' + seconds : seconds;
        $days.dataset.title = declensionNum(days, ['день', 'дня', 'дней']);
        $hours.dataset.title = declensionNum(hours, ['час', 'часа', 'часов']);
        $minutes.dataset.title = declensionNum(minutes, ['минута', 'минуты', 'минут']);
        $seconds.dataset.title = declensionNum(seconds, ['секунда', 'секунды', 'секунд']);
      }
      // получаем элементы, содержащие компоненты даты
      const $days = document.querySelector('.timer__days');
      const $hours = document.querySelector('.timer__hours');
      const $minutes = document.querySelector('.timer__minutes');
      const $seconds = document.querySelector('.timer__seconds');
      // вызываем функцию countdownTimer
      countdownTimer();
      // вызываем функцию countdownTimer каждую секунду
      timerId =...