<div class="boxes">
  <div class="box clamped">clamped</div>
  <div class="box unClamped">default</div>
</div>
body {
  overflow: visible;
  width: 100%;
  background-image: linear-gradient(
      rgba(255, 255, 255, 0.07) 2px,
      transparent 2px
    ),
    linear-gradient(90deg, rgba(255, 255, 255, 0.07) 2px, transparent 2px);
  background-size: 100px 100px, 100px 100px, 20px 20px, 20px 20px;
  background-position: -2px -2px, -2px -2px, -1px -1px, -1px -1px;
}

.boxes {
  height: 150vh;
  display: flex;
  align-items: center;
  justify-content: space-around;
}

.box {
  will-change: transform;
  padding: 0.4rem;
}
gsap.registerPlugin(ScrollTrigger);

console.log(`min:0, max:${ScrollTrigger.maxScroll(window)}`)

let boxes = gsap.utils.toArray(".box");

gsap.to('.clamped', {
    rotation: 360,
    backgroundColor: "#2c7ad2",
    duration: 1,
    scrollTrigger: {
      trigger: '.clamped',
      start: "clamp(top bottom)",
      end: "clamp(bottom top)",
      scrub: true,
      // markers: true,
      onRefresh: (self) => {
        console.log("clamped", self.start, self.end);
      }
    }
  });

gsap.to('.unClamped', {
    rotation: 360,
    backgroundColor: "#2c7ad2",
    duration: 1,
    scrollTrigger: {
      trigger: '.clamped',
      start: "top bottom",
      end: "bottom top",
      scrub: true,
      markers: true,
      onRefresh: (self) => {
        console.log("not clamped", self.start, self.end);
      }
    }
  });
















gsap.config({trialWarn: false});

External CSS

  1. https://codepen.io/GreenSock/pen/gOWxmWG.css

External JavaScript

  1. https://unpkg.co/gsap@3/dist/gsap.min.js
  2. https://assets.codepen.io/16327/ScrollTrigger.min.js?v=3.11.6h