<div id="smooth-wrapper">
<div id="smooth-content">
<div class="box box-ref">ref</div>
<div class="box box-a" data-speed="0.5">a</div>
<div class="box box-b" data-speed="0.5">b</div>
<div class="box box-c" data-speed="0.5">c</div>
<div class="refline"></div>
</div>
</div>
<div class="middle"></div>
<h2>
ref scrolls normally.<br><br>
all divs have position of top:80vh.<br><br>
a, b, and c all have data-speed:0.5<br><br>
Each object will be at it's "native" placement (with it's top edge aligned to the top of the ref element) when it is centered vertically in the viewport</h2>
:root {
--dark: #1d1d1d;
--grey-dark: #414141;
--light: #fff;
--mid: #ededed;
--grey: #989898;
--gray: #989898;
--green: #28a92b;
--green-dark: #4e9815;
--green-light: #6fb936;
--blue: #2c7ad2;
--purple: #8d3dae;
--red: #c82736;
--orange: #e77614;
accent-color: var(--green);
}
body {
background-color: #111;
font-family: "Signika Negative", sans-serif, Arial;
overscroll-behavior: none;
margin: 0;
padding: 0;
overflow-x: hidden;
}
#smooth-content {
overflow: visible;
width: 100%;
/* set a height because the contents are position: absolute, thus natively there's no height */
height: 4000px;
background-image:
linear-gradient(rgba(255,255,255,.07) 2px, transparent 2px),
linear-gradient(90deg, rgba(255,255,255,.07) 2px, transparent 2px),
linear-gradient(rgba(255,255,255,.06) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,.06) 1px, transparent 1px);
background-size: 100px 100px, 100px 100px, 20px 20px, 20px 20px;
background-position: -2px -2px, -2px -2px, -1px -1px, -1px -1px;
}
button {
position: relative;
}
.box {
width: 100px;
height: 100px;
background: linear-gradient(#61c3fb 50%, #04a8d8 50%);
position: absolute;
z-index: 100;
line-height: 100px;
font-size: 30px;
text-align: center;
will-change: transform;
}
.box-ref {
top: 80vh;
left : 100px;
}
.box-a {
top: 80vh;
left : 250px;
height:100px;
}
.box-b {
left : 400px;
top: 80vh;
height:200px
}
.box-c {
width: 100px;
height: 400px;
left : 550px;
top: 80vh;
}
.middle {
position:fixed;
top:50%;
height:2px;
width:100%;
background:red;
transform:translateY(-50%);
}
.refline {
position:absolute;
top:80vh;
background:purple;
height:2px;
width:100%;
z-index:200;
}
h2 {
margin:0;
position:fixed;
color:#eee;
padding:1em;
font-weight:normal;
background:rgb(0, 0, 0, 0.4);
}
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
// create the smooth scroller FIRST!
let smoother = ScrollSmoother.create({
smooth: 2, // seconds it takes to "catch up" to native scroll position
effects: true // look for data-speed and data-lag attributes on elements and animate accordingly
});
This Pen doesn't use any external CSS resources.