<div id="wrapper">
 <section id="content">
  <!--  smooth scrolling biz goes in here -->
  <div class="heading" aria-hidden="true">
   <p>smooooth</p>
   <div class="text-container">
    <p>scrolling</p>
    <p data-speed="0.95">scrolling</p>
    <p data-speed="0.9">scrolling</p>
    <p data-speed="0.85">scrolling</p>
    <p data-speed="0.8">scrolling</p>
    <p data-speed="0.75">scrolling</p>
    <p data-speed="0.7">scrolling</p>
   </div>
  </div>

  <section class="image-grid container">
   <div class="image_cont" data-speed="1">
    <img data-speed="auto" src="https://images.unsplash.com/photo-1556856425-366d6618905d?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTV8fG5lb258ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=60" alt="">
   </div>
   <div class="image_cont" data-speed="1.7">
    <img data-speed="auto" src="https://images.unsplash.com/photo-1520271348391-049dd132bb7c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80" alt="">
   </div>
   <div class="image_cont" data-speed="1.5">
    <img data-speed="auto" src="https://images.unsplash.com/photo-1609166214994-502d326bafee?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80" alt="">
   </div>
  </section>

  <section class="title container flow--lg">
   <h1><span class="eyebrow" aria-hidden="true">with </span>GSAP scrollsmoother</h1>
   <p>Seamlessly integrated with GSAP and ScrollTrigger. Leveraging native scrolling - no "fake" scrollbars or event hijacking.</p>
  </section>

  <section class="bars container">

   <div class="bars-text">
    <div class="flow content">
     <h2>Speed Control</h2>
     <p>Animate elements along at different speeds, slow them down or make them whizz past.</p>
    </div>

   </div>

   <div class="bars-cont">
    <div class="bar" data-speed="0.8">
     <p>0.8</p>
    </div>

    <div class="bar" data-speed="0.9">
     <p>0.9</p>
    </div>

    <div class="bar" data-speed="1">
     <p>1</p>
    </div>

    <div class="bar" data-speed="1.1">
     <p>1.1</p>
    </div>

    <div class="bar" data-speed="1.2">
     <p>1.2</p>
    </div>
   </div>

  </section>

  <section class="v-center">
   <div class="parallax-slab">
    <img data-speed="auto" src="https://assets.codepen.io/756881/smoothscroller-1.jpg" alt="">
   </div>
  </section>

  <section class="staggered container">

   <div class="staggered_text">
    <div class="flow content">
     <h2>Add some lag (the good kind!)</h2>
     <p>loosen the connection to the scroll to give a feeling of 'follow through.'</p>
    </div>

   </div>

   <div class="staggered_demo">
    <h3 id="split-stagger">stagger...</h3>
   </div>

  </section>

  <section class="parallax-images container">
   <div class="parallax-text">
    <div class="flow content">
     <h2>Easy parallax image effects</h2>
     <p>Pop your images in a container with overflow hidden, size them a little larger than the container and set data-speed to auto. GSAP does the rest.</p>
    </div>
   </div>

   <div class="image_cont">
    <img data-speed="auto" src="https://assets.codepen.io/756881/neon3.jpg" alt="">
   </div>
   <div class="image_cont">
    <img data-speed="auto" src="https://assets.codepen.io/756881/neon2.jpg" alt="">
   </div>
  </section>

  <section class="spacer"></section>
 </section>
</div>
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500&display=swap");

@font-face {
 font-family: "wild_worldbold";
 src: url("https://assets.codepen.io/756881/wild_world-webfont.woff2")
   format("woff2"),
  url("https://assets.codepen.io/756881/wild_world-webfont.woff") format("woff");
 font-weight: normal;
 font-style: normal;
}

/* @link https://utopia.fyi/type/calculator?c=320,20,1.2,1140,24,1.25,1,0,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l */

:root {
 --fluid-min-width: 320;
 --fluid-max-width: 1140;

 --fluid-screen: 100vw;
 --fluid-bp: calc(
  (var(--fluid-screen) - var(--fluid-min-width) / 16 * 1rem) /
   (var(--fluid-max-width) - var(--fluid-min-width))
 );
}

@media screen and (min-width: 1140px) {
 :root {
  --fluid-screen: calc(var(--fluid-max-width) * 1px);
 }
}

:root {
 --f-0-min: 18;
 --f-0-max: 20;
 --step-0: calc(
  ((var(--f-0-min) / 16) * 1rem) + (var(--f-0-max) - var(--f-0-min)) *
   var(--fluid-bp)
 );

 --f-1-min: 20;
 --f-1-max: 24;
 --step-1: calc(
  ((var(--f-1-min) / 16) * 1rem) + (var(--f-1-max) - var(--f-1-min)) *
   var(--fluid-bp)
 );
}

* {
 box-sizing: border-box;
}

body {
 background-color: #111;
 font-family: "Open Sans", sans-serif;
 color: white;
 overscroll-behavior: none;
 margin: 0;
 padding: 0;
 font-weight: 300;
 overflow-x: hidden;
 font-size: var(--step-0);
}

section {
 min-height: 100vh;
}

p {
 line-height: 1.35;
}

#content {
 padding: 0 0.75rem;
}

.container {
 max-width: 1100px;
 margin: 0 auto;
 padding: 0 0.5rem;
}

h1,
h2,
h3,
h4,
p {
 margin: 0;
}

.flow--lg > * + * {
 margin-top: 2em;
}

.flow > * + * {
 margin-top: 1em;
}

.title {
 text-align: center;
 display: flex;
 align-items: center;
 justify-content: center;
 flex-direction: column;
 min-height: 50vh;
}

#content {
 overflow: visible;
 width: 100%;
}

.heading {
 position: absolute;
 top: 50vh;
 left: 50%;
 transform: translateX(-50%);
 opacity: 0;
}

h1 {
 font-size: clamp(12px, 8vw, 100px);
 text-align: center;
 line-height: 0.67;
 margin: 0 auto;
 font-family: "wild_worldbold";

 .eyebrow {
  font-family: "Open sans", sans-serif;
  font-size: clamp(12px, 3vw, 40px);
  font-weight: 400;
 }
}

.heading p {
 font-family: "wild_worldbold";
 font-size: 15.5vw;
 font-size: clamp(12px, 15.5vw, 250px);
 text-align: center;
 line-height: 0.67;
 margin: 0;
 text-align: center;
 color: #111;
 -webkit-text-stroke-width: 1.5px;
 -webkit-text-stroke-color: white;
 z-index: -10;
}

.intro,
h2,
h3 {
 font-size: var(--step-1);
 font-weight: 500;
}

.text-container {
 position: relative;
}

.text-container p {
 position: absolute;
 top: 0;
 left: 0;
 right: 0;
 z-index: 999;
 color: transparent;
}

.text-container p:first-child {
 position: absolute;
 top: 0;
 left: 0;
 right: 0;
 z-index: 999;
 color: white;
}

.image-grid {
 position: relative;
 display: grid;
 grid-template-columns: repeat(3, 1fr);
 grid-template-rows: repeat(3, 1fr);
 grid-column-gap: 0.2rem;
 grid-row-gap: 0.2rem;
 width: 70vw;
 margin: 0 auto;
 padding-top: 40vh;
 z-index: -1;

 .image_cont {
  position: relative;
  aspect-ratio: 1/1;
  overflow: hidden;
 }

 img {
  position: absolute;
  top: 0;
  width: 100%;
  height: 150%;
  object-fit: cover;
 }

 .image_cont:nth-child(1) {
  grid-column: 1;
  grid-row: 1;
 }

 .image_cont:nth-child(2) {
  grid-column: 3;
  grid-row: 2;
 }

 .image_cont:nth-child(3) {
  grid-column: 2;
  grid-row: 3;
 }
}

.parallax-images {
 margin-top: 10vh;
 padding: 10rem 1rem;
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 grid-column-gap: 1rem;
 grid-row-gap: 20vh;
 align-items: center;
 justify-items: center;

 .image_cont {
  position: relative;
  height: 80vh;
  overflow: hidden;
 }

 img {
  position: absolute;
  bottom: 0;
  margin: 0 auto;
  height: 140%;
  width: 100%;
  object-fit: cover;
 }

 .parallax-text {
  grid-column: 2;
  grid-row: 1;
 }

 .image_cont:nth-child(2) {
  grid-column: 1 / span 1;
  grid-row: 1;
  width: 100%;
 }

 .image_cont:nth-child(3) {
  grid-column: 2 / span 1;
  grid-row: 2;
 }
}

.spacer {
 min-height: 50vh;
 display: flex;
 align-items: center;
 justify-content: center;
}

.stagger {
 font-size: 8vw;
}

.bars {
 display: flex;
 flex-wrap: wrap;
 column-gap: 4rem;

 .bars-text {
  flex: 1 1 300px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
 }

 .bars-cont {
  flex: 1 1 500px;
  display: flex;
  width: 100%;
  height: 60vh;
  align-items: flex-end;
 }

 .bar {
  border-radius: 10px;
  margin: 2vw;
  text-align: center;
  flex: 1 0 auto;
  font-size: var(--step-0);
  justify-self: flex-end;
  font-family: "wild_worldbold";
  font-size: clamp(16px, 3vw, 36px);
 }
}

.content {
 border-left: solid 1px white;
 padding: 0.5rem 2rem;
}

.staggered {
 display: flex;
 align-items: center;
 flex-wrap: wrap;
 column-gap: 4rem;

 h3 {
  font-family: "wild_worldbold";
  font-size: clamp(16px, 6vw, 80px);
  letter-spacing: 0.03em;
 }

 &_text {
  flex: 1 1 300px;
 }

 &_demo {
  flex: 1 1 500px;
  display: flex;
  align-items: center;
  justify-content: center;
 }
}

.parallax-slab {
 position: relative;
 height: 500px;
 width: 100%;
 max-height: 500px;
 overflow: hidden;

 img {
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 180%;
  object-fit: cover;
 }
}

.v-center {
 display: flex;
 align-items: center;
}

.spacer {
 height: 10vh;
}
View Compiled
gsap.registerPlugin(ScrollTrigger, ScrollSmoother, SplitText);

// create the smooth scroller FIRST!
const smoother = ScrollSmoother.create({
 wrapper: "#wrapper",
 content: "#content",
 smooth: 1,
 normalizeScroll: true, // prevents address bar from showing/hiding on most devices, solves various other browser inconsistencies
 ignoreMobileResize: true, // skips ScrollTrigger.refresh() on mobile resizes from address bar showing/hiding
 effects: true,
 preventDefault: true
});

gsap.set(".heading", {
 yPercent: -150,
 opacity: 1
});

let tl = gsap.timeline();
let mySplitText = new SplitText("#split-stagger", { type: "words,chars" });
let chars = mySplitText.chars;

chars.forEach((char, i) => {
 smoother.effects(char, { speed: 1, lag: (i + 1) * 0.1 });
});

// 💚 This just adds the GSAP link to this pen, don't copy this bit
import { GSAPInfoBar } from "https://codepen.io/GreenSock/pen/vYqpyLg.js";
new GSAPInfoBar({ link: "https://gsap.com/docs/v3/Plugins/ScrollSmoother/" });
// 💚 Happy tweening!

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://assets.codepen.io/16327/gsap-latest-beta.min.js?r=v3.11.3
  2. https://assets.codepen.io/16327/ScrollTrigger.min.js
  3. https://assets.codepen.io/16327/ScrollSmoother.min.js?v=94387867
  4. https://assets.codepen.io/16327/SplitText3.min.js