GSAP ScrollSmother - migrate css sticky to pin
16:20 01 May 2025

This is my section before scrollsmoother library:

// CAMERA SCALE
const historyElement = document.querySelector('.history');
const historyHeight = historyElement.offsetHeight;
const cameraTl = gsap.timeline({
  scrollTrigger: {
    trigger: ".history",
    start: "top top",
    end: `bottom-=${historyHeight / 1.5}px top`,
    scrub: 1,
    onLeave: () => {
      document.querySelector('.history__wrap').style.opacity = 0;
      document.querySelector('.history-film').style.opacity = 1;

      historyElement.style.backgroundColor = '#171819';


    },

    onEnterBack: () => {
      document.querySelector('.history__wrap').style.opacity = 1;
      document.querySelector('.history-film').style.opacity = 0;
      historyElement.style.backgroundColor = '#faf2dd';

    }
  }
});

const scaleValue = window.matchMedia("(max-width: 991px)").matches ? 10 : 22;

cameraTl.to(".history-camera > img", {
  x: 0,
  y: 0,
  scale: scaleValue,
  ease: "none",
}).to(".history-film", {
  marginTop: 0,
  y: 0,
  opacity: 1,
  ease: "none",
  duration: 0.5,
  delay: 0,
  scale: 1,

}, '-=0.2');

// FILM HISTORY
const filmHistory = gsap.utils.toArray(".history-film__item");
const filmItemWidth = filmHistory.reduce((diff, item) => {
  return diff + item.offsetWidth;
}, 0);
const filmTl = gsap.timeline({
  scrollTrigger: {
    trigger: ".history",
    scrub: 3,
    // markers: true,
    start: `top+=${historyHeight - (historyHeight / 2.5) + 100}px bottom`,
    end: () => `bottom bottom`,

    onLeave: () => {
      document.querySelector('.site-header').classList.remove('white');
    },
    onEnterBack: () => {
      document.querySelector('.site-header').classList.add('white');
    },
  }
});

filmTl.to(filmHistory, {
  x: () => `-${filmItemWidth - window.innerWidth}px`,
  ease: "none"
});

// NEXT BLOCK BG COLOR
gsap.to('.next-block', {
  scrollTrigger: {
    trigger: '.next-block',
    pinnedContainer: ".history",
    start: 'top 50%',
    toggleActions: 'play none reset none',
  }
});
.history {
  min-height: 400dvh;
  display: flex;
  /* align-items: center; */
  justify-content: flex-start;
  flex-direction: column;
  position: relative;
}

.history__wrap {
  overflow: hidden;
  min-height: 100dvh;
  width: 100vw;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  position: sticky;
  top: 0;
}

.history-text {
  text-align: center;
  margin-bottom: 40px;
}

.history-text p {
  color: var(--color-tamarillo);
  font-size: 15px;
  line-height: 22px;
  font-weight: 500;
  text-transform: uppercase;
}

.history-camera {
  text-align: center;
  position: relative;
  z-index: 2;
  width: 100%;
}

.history-heading {
  transform: rotate(-12deg);
  text-align: center;
}

.history-heading h2 {
  font-family: "PP Playground", sans-serif;
  font-size: 253px;
  line-height: 364px;
  font-weight: 500;
  color: var(--color-tamarillo);
  margin-top: -150px;
  margin-left: -110px;
}

.history-film {
  background-color: var(--color-black);
  clip-path: ellipse(300% 40% at 50% 50%);
  display: flex;
  align-items: center;
  -ms-flex-wrap: nowrap;
  flex-wrap: nowrap;
  min-height: 100dvh;
  width: 100%;
  position: relative;
  overflow-x: hidden;
  position: sticky;
  top: 30px;
  left: 0%;
  opacity: 0;
  transition: opacity 0.4s ease-out;
  scale: 0.5;
  transform-origin: center !important;
  margin-top: -100%;
}

.history-film__img {
  width: 100%;
  text-align: center;
}

.history-film__img img {
  /* clip-path: ellipse(200% 50% at 0% 50%); */
  height: 100%;
  width: 100%;
  max-width: 70%;
  object-fit: cover;
  object-position: top;
}

.history-film::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 15%;
  height: 100%;
  background: linear-gradient(to right,
      var(--color-black) 0%,
      transparent 100%);
  z-index: 3;
}

.history-film::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 10%;
  height: 100%;
  background: linear-gradient(to left, var(--color-black) 0%, transparent 100%);
  z-index: 3;
}

.history-film__item {
  min-width: 50vw;
  height: 80dvh;
  background-color: var(--color-black-light);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-direction: column;
  padding: 50px 0px;
}

.history-film__item.large {
  min-width: 100vw;
}

.history-film__content {
  display: flex;
  justify-content: center;
  width: 100%;
  padding: 50px 20px;
  flex: 1;
  height: calc(100% - 100px);
}

.history-film__text {
  max-width: 90%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 25px 0px;
}

.history-film__content h2 {
  font-family: "PP Playground", sans-serif;
  font-size: 9em;
  line-height: 1;
  font-weight: 500;
  color: var(--color-warm-white);
}

.history-film__content p {
  font-size: 1.2em;
  line-height: 1.467;
  font-weight: 500;
  color: var(--color-warm-white);
  text-transform: uppercase;
}

.history-film__dots {
  display: flex;
  align-items: center;
  justify-content: space-around;
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
}

.history-film__dots li {
  width: 3.05vw;
  height: 3.05vw;
  background-color: var(--color-black);
}

.history-film-mask {
  display: flex;
  align-items: center;
  -ms-flex-wrap: nowrap;
  flex-wrap: nowrap;
  position: relative;
}

estd 1954

History

1968

Sve je počelo 1968. godine, u maloj ulici na obodu grada. Naš deda, Radomir, otvorio je prvu radnju sa samo jednom stolicom, starim ogledalom i makazama koje je dobio na poklon. Kroz vitraž prozor upadala je svetlost koja je osvetljavala prve mušterije — radnike, đake, prolaznike koji su tražili malo razgovora i dobru frizuru.

1968

Godine su prolazile, i berbernica je rasla zajedno sa komšilukom. Prvu električnu mašinu dobili smo sedamdesetih, a ogledalo je zamenilo novo, šire, ali su makaze ostale iste. I duh. Danas, kada uđete u našu radnju, još uvek možete osetiti miris starog losiona, čuti zvuk radio aparata i videti fotografije koje pričaju priču dužu od pola veka.

Can any help me?

I try to solve sticky problem with gsap because i use lenis.js before, but after gsap become free i want to migrate on new way of smooth scrolling.

Lenis.js and GSAP handle smooth scrolling in different ways:

Lenis.js uses a custom scroll wrapper and requestAnimationFrame, which means it's not using native browser scroll.

GSAP's ScrollSmoother (the new free plugin you're referring to) also uses a scroll proxy, but it's designed to integrate deeply with GSAP animations.

Because both libraries override the native scroll behavior, switching from Lenis to GSAP’s ScrollSmoother can break sticky positioning (position: sticky) if not configured properly.

javascript css animation gsap smooth-scrolling