<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

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js