Wheel Picker
iOS-style wheel columns for month, day and year with drag, mouse wheel, click and an optional tick sound.
Preview and code
index.html
<div class="wp"><p class="bn">Born <b></b></p><div class="bx"><div class="hl"></div><div class="cl"><div class="ls"></div></div><div class="cl"><div class="ls"></div></div><div class="cl"><div class="ls"></div></div></div><label class="tk"><input type="checkbox"><i></i><span>Tick sound</span></label></div>
styles.css
.wp{width:100%;height:100%;min-height:380px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;font-family:system-ui,-apple-system,sans-serif;color:#eee;}.bn{margin:0;font-size:12px;color:#888}.bn b{color:#fff}.bx{position:relative;display:flex;gap:4px;background:#161616;border:1px solid #2a2a2a;border-radius:18px;padding:0 6px;width:280px;box-sizing:border-box}.hl{position:absolute;left:6px;right:6px;top:68px;height:34px;background:#222;border-radius:10px}.cl{position:relative;height:170px;overflow:hidden;touch-action:none;cursor:grab;flex:1}.cl:first-of-type{flex:1.4}.ls{position:absolute;left:0;right:0;top:68px;transition:transform .35s cubic-bezier(.2,.9,.3,1)}.ls.d{transition:none}.ls div{height:34px;display:flex;align-items:center;justify-content:center;font-size:13px;color:#888;transition:color .2s,opacity .2s}.ls div.c{color:#fff;font-weight:700}.tk{display:flex;align-items:center;gap:8px;font-size:12px;cursor:pointer}.tk input{display:none}.tk i{width:36px;height:20px;border-radius:99px;background:#333;position:relative;transition:background .25s}.tk i:after{content:"";position:absolute;left:3px;top:3px;width:14px;height:14px;border-radius:50%;background:#fff;transition:transform .3s cubic-bezier(.3,1.5,.5,1)}.tk input:checked+i{background:#0a84ff}.tk input:checked+i:after{transform:translateX(16px)}
script.js
(function(){var R=document.querySelector(".wp"),H=34,M=["January","February","March","April","May","June","July","August","September","October","November","December"],D=[],Y=[];for(var i=1;i<=31;i++)D.push(i);for(i=1990;i<=2030;i++)Y.push(i);var L=[M,D,Y],ix=[5,8,14],cols=[].slice.call(R.querySelectorAll(".cl")),ctx=null,snd=R.querySelector(".tk input");function tick(){if(!snd.checked)return;try{ctx=ctx||new(window.AudioContext||window.webkitAudioContext)();var o=ctx.createOscillator(),g=ctx.createGain();o.frequency.value=1400;g.gain.value=.04;o.connect(g);g.connect(ctx.destination);o.start();o.stop(ctx.currentTime+.02)}catch(e){}}function head(){R.querySelector(".bn b").textContent=M[ix[0]]+" "+D[ix[1]]+", "+Y[ix[2]]}function paint(c,f,snap){var ls=cols[c].querySelector(".ls");ls.classList.toggle("d",!snap);ls.style.transform="translateY("+(-f*H)+"px)";var r=Math.round(f);[].forEach.call(ls.children,function(e,k){e.className=k===r?"c":"";e.style.opacity=Math.max(.15,1-Math.abs(k-f)*.28)})}function set(c,v){v=Math.max(0,Math.min(L[c].length-1,v));if(v!==ix[c])tick();ix[c]=v;paint(c,v,true);head()}cols.forEach(function(el,c){var ls=el.querySelector(".ls");L[c].forEach(function(t,k){var d=document.createElement("div");d.textContent=t;d.onclick=function(){set(c,k)};ls.appendChild(d)});var sy=0,sf=0,dr=false;el.onpointerdown=function(e){dr=true;sy=e.clientY;sf=ix[c];el.setPointerCapture(e.pointerId)};el.onpointermove=function(e){if(!dr)return;var f=Math.max(0,Math.min(L[c].length-1,sf-(e.clientY-sy)/H));paint(c,f,false);var r=Math.round(f);if(r!==ix[c]){ix[c]=r;tick();head()}};el.onpointerup=function(){dr=false;set(c,ix[c])};el.onwheel=function(e){e.preventDefault();set(c,ix[c]+(e.deltaY>0?1:-1))};paint(c,ix[c],true)});head()})();