[GSAP] ScrollTrigger의 pin 속성 제대로 이해하기!🎯

choii_ii·2025년 3월 11일
post-thumbnail

며칠 전, 면접관님을 통해 알게되었던 새로운 gsap 속성이 있었다.
그거슨 바로 ScrollTrigger 속성 중 하나인 pin 속성!!

대표적으로 엔터프라이즈블록체인 프로젝트에서 position:sticky; 를 사용하여 스크롤 시, 특정 요소를 고정시키는 인터랙션을 구현한 방법이있다.
해당 모션에 대해 pin 속성을 사용할 수도 있었는데 사용하지 않은 이유에 대해 여쭤보셨다.
그때의 동공지진이란...🥲 (쫄지말자 초이야.. * 100번 외친듯)
이미 html과 css로 마크업을 다 해둔 상태였긴 했지만, 사실 pin 속성이 정확히 어떤 성질을 갖고 있는 것인지는 숙지하지 못했었다.
(괜찮아 이제부터 알면 되지. 원래 극한의 상황에서 배운 것이 더 기억에 잘 남잖아..🥲)


📌 pin이 도대체 뭔데?

🩵 디자인 시안이나 인터랙션 구현에 있어서 "이 요소는 고정시키고 싶다!" 하는 순간이 있다면, 이런 순간을 위해 딱 맞는 기능이 바로 pin 속성이다.

🩵 pin 속성은 단어 그대로 특정 요소를 화면에 고정하는 역할을 한다. 즉, position:sticky;처럼 스크롤을 내리더라도 해당 요소가 정해진 영역에서 고정되어있는 것처럼 계속 머무르는 효과를 보여준다.

🩵 gsap에서는 position:sticky;보다 더 유연하게 조정할 수 있다.

💫 pin 이럴 때 사용해요!

🔸 섹션 강조 : 특정 영역에서 콘텐츠를 고정하면서 강조할 때
🔸 스크롤 인터랙션 : 스크롤 시, 특정 요소가 변하는 효과를 줄 때
🔸 sticky UI : 페이지 네비게이션이나 특정 이미지 등을 고정할 때


📌 pin 도대체 어떻게 사용하는건데?

🛠️ 기본 사용법

🩵 기본적으로 pin:true의 설정만으로도 고정이 가능하다.

🩵 아래 코드를 보면 .box는 고정시킬 대상요소가 되고 .container는 고정의 기준이 되는 trigger를 의미한다. 즉, .box 요소는 .container 요소 안에서 스크롤 시 특정 위치에 고정이 되는 것이다. (특정위치는 start & end로 언제부터 언제까지 고정시킬지 설정한 값에 따라 달라진다.)
🔸 trigger: 어느 요소를 기준으로 할지 설정 (=.container)
🔸 start & end: 언제부터 언제까지 고정할지
🔸 pin: true: 해당 요소를 고정시키는 옵션

// 요소 고정하기
gsap.to(".box", {
  scrollTrigger: {
    trigger: ".container", // 고정할 기준 요소
    start: "top top", 
    end: "bottom top",
    pin: true, // 요소 고정!
    markers: true
  }
});

🛠️ 추가 옵션 & 유용한 기능

🩵 pinSpacing: false -> 고정될 때 원래 공간만큼 여백이 생기는데, 그걸 없애고 싶다면?! 이 옵션을 추가하여 불필요한 공간을 제거한다.

🩵 pinReparent: true -> 부모 요소의 레이아웃이 깨질 때 해결하는 방법! 이 옵션을 추가하면 특정 레이아웃에서 문제가 생길 때 해결할 수 있다. 하지만 자주 사용되는 옵션은 아니다.

🩵 anticipatePin : 1 -> 스크롤 성능이 느려지는 게 느껴질 때 살짝 미리 고정하는 옵션! 기본값은 0이고 숫자를 올리면 미리 고정된다. 이 옵션을 조절하면 부드러운 스크롤링을 유지할 수 있다.


📌 이제 sticky 들어가시고, pin 나와!

🩵 비주얼 영상/이미지는 고정된 채로 스크롤할 때 텍스트가 바뀌는 효과로 웹 사이트에서 많이 쓰이는 인터랙션이다. (ex-Apple에서 제품 홍보 시, 정말 많이 볼 수 있는 효과이다.)

🥨 기존 sticky 활용 코드

🩵 [HTML]
🔸 .sticky-wrap 요소가 고정이 될 대상 요소이다.

<body>
<section class="sc-intro">
	<div class="sticky-wrap">
		<!-- intro bg video -->
		<div class="intro__bg">
			<video id="video" loop autoplay muted playsinline poster="./assets/images/intro-poster.jpg">
				<source src="./assets/video/Archivo-VariableFont_Medium_C_PC.mp4" type="video/mp4">
            </video>
		</div>
		<!-- // intro bg video -->
        
		<!-- intro text -->
		<div class="group-intro-text">
        	<!-- text 중략 -->
        </div>
		<!-- // intro text -->
	</div>
</section>
</body>

🩵 [CSS]
🔸 고정의 기준이 되는 .sc-intro 요소에 position:relative;를 설정해주고 대략적인 높이도 설정했다.

🔸 고정이 되는 .sticky-wrap 요소에 position:sticky;를 설정했다.

<style>
.sc-intro{
	position: relative;
    width: 100%;
    height: calc(100vh * 8);
}

.sticky-wrap{
	position: sticky;
    width: 100%;
    height: 100vh;
    top: 0;
    left: 0;
    overflow: hidden;
}
</style>

🩵 [script (GSAP)]
🔸 text 애니메이션을 제외한 scrollTrigger만 작성한 스크립트이다. .sc-intro 영역의 시작점과 끝점을 설정했다.

<script>
const intro = gsap.timeline({
  scrollTrigger: {
    trigger: '.sc-intro',
    start: '0% 0%',
    end: '100%, 100%',
    // markers: true,
    scrub: true
  }
});
</script>

🥨 pin 속성으로 적용한 코드

🩵 [css]
🔸 position:sticky;를 사용했던 style은 pin 속성으로 대체할 것이기 때문에 relative;로 바꿔준다.

<style>
.sticky-wrap {
  position: relative; /* position: sticky를 사용하지 않음 */
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
</style>

🩵 [script (GSAP)]
🔸 고정시킬 .sticky-wrap 요소에 대한 스크립트를 추가 작성한다.

🔸 다른 모션과 달리 css 속성을 별도로 설정할 필요 없이, scrollTrigger만 설정해주면(특히 pin:true) 스크롤의 기준이 되는 시작점과 끝점에 맞춰 해당 요소를 고정시켜준다.

gsap.to(".sticky-wrap", {
  scrollTrigger: {
    trigger: ".sc-intro",  // .sc-intro 영역을 기준으로 고정
    start: "0% 0%",         // 시작점
    end: "100% 100%",       // 끝점
    pin: true,              // .sticky-wrap 고정
    scrub: true,            // 스크롤에 따라 부드럽게 애니메이션
    markers: true           // 마커 추가 (디버깅 용)
  }
});

👩🏻‍💻 : 이제 완벽하게 알아버렸다. ㅎㅎ 반응형 제작할 때에도 유용하고 효율적으로 컨트롤 가능하다고 알려주신 점도 꼭 기억하고 있다가 반응형 테스트 해봐야지!!!!

profile
퍼블리셔 / 작업 기로끄v

0개의 댓글