Flip Clock
A copy-paste countdowns component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.
CountdownsHTMLCSSJavaScriptany framework
00
HRS12
MIN45
SECCopy into your project
HTML
<div class="nuda-flip-clock" role="timer" aria-label="Countdown timer">
<div class="nuda-flip-clock__unit">
<div class="nuda-flip-clock__card" data-unit="hours">
<span class="nuda-flip-clock__top">0</span>
<span class="nuda-flip-clock__bottom">0</span>
</div>
<span class="nuda-flip-clock__label">HRS</span>
</div>
<span class="nuda-flip-clock__sep">:</span>
<div class="nuda-flip-clock__unit">
<div class="nuda-flip-clock__card" data-unit="minutes">
<span class="nuda-flip-clock__top">0</span>
<span class="nuda-flip-clock__bottom">0</span>
</div>
<span class="nuda-flip-clock__label">MIN</span>
</div>
<span class="nuda-flip-clock__sep">:</span>
<div class="nuda-flip-clock__unit">
<div class="nuda-flip-clock__card" data-unit="seconds">
<span class="nuda-flip-clock__top">0</span>
<span class="nuda-flip-clock__bottom">0</span>
</div>
<span class="nuda-flip-clock__label">SEC</span>
</div>
</div>CSS
/* Flip Clock
Flip-style countdown with card flip animation.
Customize: --flip-bg, --flip-text, --flip-radius */
.nuda-flip-clock {
--flip-bg: #1a1a1a;
--flip-text: #fff;
--flip-radius: 6px;
display: flex;
align-items: flex-start;
gap: 0.5rem;
}
.nuda-flip-clock__unit {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.nuda-flip-clock__card {
position: relative;
width: 48px;
height: 60px;
perspective: 200px;
}
.nuda-flip-clock__top,
.nuda-flip-clock__bottom {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 50%;
background: var(--flip-bg);
color: var(--flip-text);
font-size: 1.4rem;
font-weight: 700;
font-variant-numeric: tabular-nums;
overflow: hidden;
}
.nuda-flip-clock__top {
border-radius: var(--flip-radius) var(--flip-radius) 0 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.nuda-flip-clock__bottom {
border-radius: 0 0 var(--flip-radius) var(--flip-radius);
}
.nuda-flip-clock__card--flipping .nuda-flip-clock__top {
animation: nuda-flip-down 0.6s ease-in-out;
}
@keyframes nuda-flip-down {
0% { transform: rotateX(0); }
50% { transform: rotateX(-90deg); }
100% { transform: rotateX(0); }
}
.nuda-flip-clock__sep {
color: #555;
font-size: 1.4rem;
font-weight: 700;
line-height: 60px;
}
.nuda-flip-clock__label {
color: #666;
font-size: 0.6rem;
text-transform: uppercase;
letter-spacing: 0.1em;
}
@media (prefers-reduced-motion: reduce) {
.nuda-flip-clock__card--flipping .nuda-flip-clock__top {
animation: none;
}
}JavaScript
/* Flip Clock — Countdown with flip animation.
Set your target date below. */
(function () {
var clock = document.querySelector('.nuda-flip-clock');
if (!clock) return;
// Set target to 1 hour from now (customize as needed)
var target = new Date(Date.now() + 3600000);
var cards = {
hours: clock.querySelector('[data-unit="hours"]'),
minutes: clock.querySelector('[data-unit="minutes"]'),
seconds: clock.querySelector('[data-unit="seconds"]')
};
function pad(n) {
return n < 10 ? '0' + n : String(n);
}
function update() {
var diff = Math.max(0, target - Date.now());
var h = Math.floor(diff / 3600000);
var m = Math.floor((diff % 3600000) / 60000);
var s = Math.floor((diff % 60000) / 1000);
setCard(cards.hours, pad(h));
setCard(cards.minutes, pad(m));
setCard(cards.seconds, pad(s));
if (diff > 0) requestAnimationFrame(tick);
}
function setCard(card, value) {
if (!card) return;
var top = card.querySelector('.nuda-flip-clock__top');
var bottom = card.querySelector('.nuda-flip-clock__bottom');
if (top.textContent !== value) {
card.classList.add('nuda-flip-clock__card--flipping');
top.textContent = value;
bottom.textContent = value;
setTimeout(function () {
card.classList.remove('nuda-flip-clock__card--flipping');
}, 600);
}
}
var last = 0;
function tick(ts) {
if (ts - last >= 1000) {
last = ts;
update();
}
if (target - Date.now() > 0) requestAnimationFrame(tick);
}
update();
requestAnimationFrame(tick);
})();How to use Flip Clock
Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.
Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.