<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;
}
View Compiled
// 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);
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.