JSFiddle - React, Tailwind, and code Playground

by mori57

HTML

<h1>Scrollable "field"</h1>
<p>This is a scrollable field that snaps to the nearest height of the row that you stop scrolling on. It even appears to work on a tablet.</p>

<div class="surround">
    <div class="valuelist"></div>
</div>

CSS

.surround {
    width:100px;
    height:50px;
    overflow:hidden;
    text-align:center;
    margin:2em auto;
    border: 1px solid black;
    border-radius: 20%;
}

.valuelist {
    overflow-x:hidden;
    overflow-y:auto;
    height:50px;
    margin-right:-20px; /* Trying to hide the scrollbar, here, outside the container's area */
}

.valuelist div {
    font-size:50px;
    line-height:50px;
    height:50px;
}

JavaScript

// Get a reference to the surround "mask"
var $surr = $(".surround");
// and a reference to the scrolling container of values
var $valList = $(".valuelist");
// this is an object intended to act as our timer
var scrollPause;

// initialize our scroller with values from 0 to 100
for (var i = 0; i< 101; i++){
    // create a single div for each item and append it to the list
    var item = "<div>" + i + "</div>";
    $valList.append($(item));   
}

/* adjustScroll : 
 *     this method corrects the scroll position to round up or down
 *     to snap it so that a value doesn't appear half or partially
 *     scrolled.
 */
var adjustScroll = function(){
    // get the position of the scrolling area
    var currScroll = $valList.scrollTop();
    // find the height of the individual div items within
    var inc = $(".valuelist div").height();
    // divide the position by the increment height
    var itemLine = currScroll/inc;
    // round that value and multiply it by the increment 
    // to find the corrected position
    var itemCorrectedPos = Math.round(itemLine) *inc;
    // quickly animate the scroll position to the corrected value
    $valList.animate({
        scrollTop: itemCorrectedPos
    },1);
};

$valList.scroll(function(ev){
    window.clearTimeout(scrollPause);
    scrollPause = window.setTimeout(adjustScroll,50);
});