<div class="scrub-wrapper">
<div class="sticky-video-container">
<video id="scroll-video" muted playsinline src="https://codeshack.io/web/example.mp4"></video>
<div class="overlay-text">
<h2>Scroll to control time</h2>
<p>The video plays forwards and backwards as you move down and up.</p>
</div>
</div>
<div class="scroll-height-spacer"></div>
</div>
*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
margin: 0;
background: #000000;
color: #ffffff;
}
.scrub-wrapper {
position: relative;
width: 100%;
}
.sticky-video-container {
position: sticky;
top: 0;
height: 100vh;
width: 100%;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
#scroll-video {
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0.6;
}
.overlay-text {
position: absolute;
text-align: center;
z-index: 10;
pointer-events: none;
padding: 20px;
}
.overlay-text h2 {
font-size: clamp(2rem, 5vw, 4rem);
margin-bottom: 10px;
}
.overlay-text p {
font-size: 1.25rem;
color: #cbd5e1;
margin: 0;
}
.scroll-height-spacer {
height: 400vh;
width: 100%;
}
const video = document.getElementById("scroll-video");
const container = document.querySelector(".scrub-wrapper");
video.addEventListener("loadedmetadata", () => {
window.addEventListener("scroll", () => {
const rect = container.getBoundingClientRect();
const scrollStart = rect.top;
const scrollHeight = rect.height - window.innerHeight;
let progress = -scrollStart / scrollHeight;
progress = Math.max(0, Math.min(1, progress));
if (!isNaN(video.duration)) {
video.currentTime = progress * video.duration;
}
});
});