JSFiddle - React, Tailwind, and code Playground
HTML
<button id="down">down</button>
<div id="outer">
<div id="container">
<div id="inner">
<div id="animated">
</div>
</div>
</div>
<hr id="max" />
</div>
CSS
#outer {
position: relative;
width: 300px;
height: 300px;
background-color: #eee;
}
#container {
width: inherit;
height: inherit;
overflow-y: scroll;
overflow-x: hidden;
}
#inner {
width: 300px;
height: 2000px;
background-color: inherit;
}
#animated {
margin: 50px;
background-color: #33aa66;
width: 50px;
height: 50px;
}
#max {
position: absolute;
top: 200px;
background-color: #aa3333;
width: 100%;
height: 3px;
}
JavaScript
var new_margin;
var step = 75;
$('#down').click(function () {
scroll(1000);
});
var scrollTimer = null;
$("#container").bind("scroll", function () {
clearTimeout(scrollTimer);
scrollTimer = setTimeout(function () { debugger; scroll(1); }, 10);
});
function scroll(speed) {
var scrollStep, animationStep = step;
var currentBoxBottom = $("#animated")[0].offsetTop + $("#animated")[0].offsetHeight;
var nextCurrentBoxBottom = currentBoxBottom + step;
var limit = $("#max")[0].offsetTop + $("#container")[0].scrollTop;
if (nextCurrentBoxBottom > limit) {
if (limit >= $("#container")[0].scrollTop) {
scrollStep = $("#container")[0].scrollTop + nextCurrentBoxBottom - limit;
}
else {
scrollStep = $("#container")[0].scrollTop - nextCurrentBoxBottom - limit;
animationStep = nextCurrentBoxBottom - limit;
}
$("#container")[0].scrollTop = scrollStep;
}
new_margin = animationStep + parseInt($('#animated').css('margin-top'));
$("#animated").animate({ marginTop: new_margin }, speed);
}