Odometer Number Roll
A mechanical odometer where each digit column rolls vertically to the new number.
<div class="odo" id="odo"><span class="odo-d" data-n="0">0</span><span class="odo-d" data-n="0">0</span><span class="odo-d" data-n="0">0</span><span class="odo-d" data-n="0">0</span></div>
<button class="odo-btn" id="odoBtn">Animate</button>body{background:#0d1426;flex-direction:column;gap:20px}
.odo{display:flex;gap:4px;background:#141d33;padding:14px 18px;border-radius:14px}
.odo-d{position:relative;width:38px;height:54px;overflow:hidden;font:800 40px/54px ui-monospace,monospace;color:#fff;text-align:center}
.odo-col{position:absolute;left:0;top:0;width:100%;transition:transform 1.2s cubic-bezier(.3,0,.1,1)}
.odo-col span{display:block;height:54px}
.odo-btn{font:600 14px/1 system-ui,sans-serif;color:#fff;background:#ff477e;border:0;border-radius:10px;padding:11px 24px;cursor:pointer}var digits=document.querySelectorAll('.odo-d');
digits.forEach(function(d){var col=document.createElement('div');col.className='odo-col';for(var i=0;i<=9;i++){var s=document.createElement('span');s.textContent=i;col.appendChild(s)}d.innerHTML='';d.appendChild(col)});
function set(num){var str=String(num).padStart(4,'0');digits.forEach(function(d,i){d.querySelector('.odo-col').style.transform='translateY(-'+(+str[i]*54)+'px)')})}
document.getElementById('odoBtn').onclick=function(){set(Math.floor(Math.random()*9000+1000))};
set(2026);Free to use.This snippet is plain HTML, CSS and JavaScript with no dependencies. Copy any file, or download the whole thing as a single ready-to-open .html page.