<input id="triggerAnimation" type="checkbox" />

<div class="timer">
  <div class="digit seconds">
    <span>9</span>
    <span>8</span>
    <span>7</span>
    <span>6</span>
    <span>5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span>
    <span>0</span> 
  </div><div class="digit milliseconds">
    <span>9</span>
    <span>8</span>
    <span>7</span>
    <span>6</span>
    <span>5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span> 
    <span>0</span>
  </div>
</div>

<aside>
  <label>
    <span>Font colour:</span>
    <input id="fontColour" type="color" value="#000000" />
  </label>
  <label>
    <span>Background colour:</span>
    <input id="bgColour" type="color" value="#ffffff" />
  </label>
  <label for="triggerAnimation" class="toggle">
    <span>Start</span>
    <span>Reset</span>
  </label>
</aside>
:root {
  --fontColour: #000000;
  --bgColour: #ffffff;
}

body {
  display: flex;
  height: 100vh;
}

.timer {
  overflow: hidden;
  margin: auto;
  height: 1em;
  width: 2ch;
  text-align: center;
  font-size: calc(5vw + 9em);
  background-color: var(--bgColour, white);
  padding: 0 0.125em;
}

@media screen and (min-width: 360px) {
  .timer {
    font-size: 15em;
  }
}

.digit {
  display: inline-block;
  margin-top: -0.1em; /* adjustment based on font used */
  color: var(--fontColour, black);
}

.digit span {
  display: block;
  width: 100%;
  height: 1em;
}

input[type="checkbox"]:checked ~ .timer .seconds {
  animation: seconds 10s 1 step-end forwards;
}

input[type="checkbox"]:checked ~ .timer .milliseconds {
  animation: milliseconds 1s 10 step-end forwards;
}

@keyframes seconds {
  0%  { transform: translateY(0) }
  10% { transform: translateY(-1em) }
  20% { transform: translateY(-2em) }
  30% { transform: translateY(-3em) }
  40% { transform: translateY(-4em) }
  50% { transform: translateY(-5em) }
  60% { transform: translateY(-6em) }
  70% { transform: translateY(-7em) }
  80% { transform: translateY(-8em) }
  90% { 
    transform: translateY(-10em);
    width: 0;
  }
  100% { 
    transform: translateY(-10em);
    width: 0;
  }
}

@keyframes milliseconds {
  0%      { transform: translateY(0) }
  10%     { transform: translateY(-1em)  }
  20%     { transform: translateY(-2em)  }
  30%     { transform: translateY(-3em)  }
  40%     { transform: translateY(-4em)  }
  50%     { transform: translateY(-5em)  }
  60%     { transform: translateY(-6em)  }
  70%     { transform: translateY(-7em)  }
  80%     { transform: translateY(-8em)  }
  90%     { transform: translateY(-9em)  }
  100%    { transform: translateY(-9em)  }
}

// For triggering the countdown animation with a checkbox
.toggle span {
  font-size: 1.2em;
  padding: 0.5em;
  background-color: palegreen;
  cursor: pointer;
  border-radius: 4px;
}

input[type="checkbox"] {
  opacity: 0;
  position: absolute;
}

 input[type="checkbox"]:checked ~ aside .toggle span:first-of-type {
  display: none;
}

.toggle span:nth-of-type(2) {
  display: none;
}

input[type="checkbox"]:checked ~ aside .toggle span:nth-of-type(2) {
  display: inline;
}

// Just to show that font colour and background colour can be customised
aside {
  position: fixed;
  top: 0;
  right: 0;
  padding: 1em;
}

aside label {
  display: flex;
  justify-content: end;
  align-items: center;
  margin-bottom: 0.5em;
}
// Unrelated to actual timer, it's just a colour thing
let root = document.documentElement;
const fontColourInput = document.getElementById('fontColour');
const bgColorInput = document.getElementById('bgColour');

fontColourInput.addEventListener('input', updateFontColour, false);
bgColorInput.addEventListener('input', updateBgColour, false);

function updateFontColour(event) {
  root.style.setProperty('--fontColour', event.target.value);
}

function updateBgColour(event) {
  root.style.setProperty('--bgColour', event.target.value);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.