Skip to content

Number Roll

A copy-paste countdowns component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.

CountdownsHTMLCSSJavaScriptany framework
0123456789
0123456789
0123456789

Copy into your project

HTML
<div class="nuda-number-roll" role="timer" aria-label="Counter">
  <div class="nuda-number-roll__digit">
    <div class="nuda-number-roll__strip" data-target="3">
      <span>0</span><span>1</span><span>2</span><span>3</span><span>4</span>
      <span>5</span><span>6</span><span>7</span><span>8</span><span>9</span>
    </div>
  </div>
  <div class="nuda-number-roll__digit">
    <div class="nuda-number-roll__strip" data-target="7">
      <span>0</span><span>1</span><span>2</span><span>3</span><span>4</span>
      <span>5</span><span>6</span><span>7</span><span>8</span><span>9</span>
    </div>
  </div>
  <div class="nuda-number-roll__digit">
    <div class="nuda-number-roll__strip" data-target="2">
      <span>0</span><span>1</span><span>2</span><span>3</span><span>4</span>
      <span>5</span><span>6</span><span>7</span><span>8</span><span>9</span>
    </div>
  </div>
</div>
CSS
/* Number Roll
   Slot-machine style digit roll animation.
   Customize: --roll-bg, --roll-text, --roll-digit-size */

.nuda-number-roll {
  --roll-bg: #1a1a1a;
  --roll-text: #fff;
  --roll-digit-height: 40px;
  --roll-digit-width: 32px;
  display: flex;
  gap: 2px;
}

.nuda-number-roll__digit {
  width: var(--roll-digit-width);
  height: var(--roll-digit-height);
  background: var(--roll-bg);
  border-radius: 6px;
  overflow: hidden;
  position: relative;
}

.nuda-number-roll__strip {
  display: flex;
  flex-direction: column;
  transition: transform 1.5s cubic-bezier(0.22, 1, 0.36, 1);
}

.nuda-number-roll__strip span {
  width: var(--roll-digit-width);
  height: var(--roll-digit-height);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--roll-text);
  font-size: 1.2rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

@media (prefers-reduced-motion: reduce) {
  .nuda-number-roll__strip {
    transition: none;
  }
}
JavaScript
/* Number Roll — Rolls digits to a target value.
   Set data-target on each .nuda-number-roll__strip element. */

(function () {
  var strips = document.querySelectorAll('.nuda-number-roll__strip');
  if (!strips.length) return;

  strips.forEach(function (strip, i) {
    var target = parseInt(strip.getAttribute('data-target') || '0', 10);
    var digitH = strip.querySelector('span').offsetHeight;

    // Slight stagger per digit
    setTimeout(function () {
      strip.style.transform = 'translateY(-' + (target * digitH) + 'px)';
    }, i * 150);
  });
})();

How to use Number Roll

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.

More countdowns components

← Browse all NudaUI components