JSFiddle - React, Tailwind, and code Playground
by Joe Pea
HTML
<div class="wrapper">
<div class="inner">
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
large div<p/><p /><p /><p />
...
CSS
.wrapper {
/*for reference*/
border: 3px solid green;
}
.inner {
width: 100px;
background: pink;
/*so you can see when you reached the bottom*/
border-bottom: 10px solid teal;
}
* {
box-sizing: border-box;
}
body, html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
overflow: scroll;
}
body {
padding: 10px;
width: calc(100% / var(--scale));
height: calc(100% / var(--scale));
transform-origin: top left;
transform: scale(var(--scale));
}
JavaScript
const inner = document.querySelector('.inner')
const wrapper = document.querySelector('.wrapper')
const body = document.body
const scale = 4
document.body.style.setProperty('--scale', scale)
body.addEventListener('scroll', () => {
// on scroll, translate the scrolled object to account for scale,
// so that it moves at the same speed as a finger on the screen
// (or same speed as we're used to scrolling with the mouse or touchpad).
inner.style.transform = `translateY( calc( ${body.scrollTop}px * ( 1 - 1 / ${scale} ) ) )`
})
// pre-calc the height of the wrapper
const bodyHeight = parseFloat(getComputedProperty(body).height)
const maxScrollTop = body.scrollHeight - bodyHeight
const wrapperHeight = parseFloat(getComputedStyle(wrapper).height)
const adjustedWrapperHeight = wrapperHeight + (maxScrollTop * ( 1 - 1 / scale )) + 'px'
console.log(wrapperHeight, adjustedWrapperHeight)
wrapper.style.height = adjustedWrapperHeight