<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="pin">
<p>
fixed <br>
element <br>
momentum <br>
scroll <br>
effect <br>
</p>
</div>
*{ backface-visibility: hidden;}
.section{
height: 100vh;
&:nth-child(odd){ background: #eadaea;}
&:nth-child(even){ background: #daeada;}
}
.pin{
position: fixed;
top: 30%;
left: 30%;
width: 40%;
height: 40vh;
box-sizing: border-box;
padding: 2rem;
background: white;
box-shadow: 0 1rem 5rem -2rem rgba(black,0.5);
transition: transform 100ms linear;
p{
font-size: 5vmin;
font-family: "Helvetica", "Avenir Next", sans-serif;
line-height: 1.25;
font-weight: 600;
color: black;
position: relative;
top: 50%;
transform: translatey(-50%);
}
}
View Compiled
//config vars
const lagAmount = 50;
const maxSpeed = 100;
const frameRate = 20;
const selector = '.pin';
//code
let scrollTop = 0;
let pinTop = 0;
let lastTime;
const updatePinPosition = (time) => {
if (!lastTime)
lastTime = time;
let delta = time - lastTime;
if (delta >= frameRate){
scrollTop = $(window).scrollTop();
var move = (scrollTop - pinTop) * delta / (lagAmount + delta);
var direction = move === 0 ? 0 : move / Math.abs(move);
pinTop = pinTop + Math.min( Math.abs(move), maxSpeed ) * direction;
$(selector).css('transform', `translateY(${-move}px`)
lastTime = time;
}
requestAnimationFrame(updatePinPosition);
}
requestAnimationFrame(updatePinPosition);
View Compiled
This Pen doesn't use any external CSS resources.