통합검색

Javascript

[GSAP] ScrollSmoother 사용시 #해시 클릭하면 해당 id의 엘리먼트로 scrollTo 처리

  • 2026.01.21 17:07:34


GSAP에서 ScrollSmoother 사용시 부드러운 스크롤링이 작동하는데,
a 태그의 #링크 클릭시 해당 id의 엘리먼트로 스크롤이 이동해야 하는 상황.
또는, domain.com/page.html#sec1 과 같이 주소로 접속한 경우에도 해당 id의 엘리먼트로 스크롤이 이동해야 하는 상황.

일반적인 방법으로 offset.top 만큼 scorllTo 하게 되면 ScrollSmoother 가 위치를 잡지 못하므로
아래 코드를 활용하면 된다.



[!]HTML 코드[/!] 
<ul class="product_tab2">
        <li class="active"><a href="#sec1">LG U+ LTE</a></li>
        <li><a href="#sec2">LG U+ 5G</a></li>
        <li><a href="#sec3">SKT</a></li>
        <li><a href="#sec4">KT</a></li>
        <li><a href="#sec5">모바일라우터</a></li>
</ul>

[!]Javascript(GSAP) 코드[/!] 
// # 클릭시 해당영역 이동
(() => {
  const links = document.querySelectorAll('.product_nav a, .product_tab2 a');
  const OFFSET = 100; // 위가 잘리면 늘리고(80~140), 너무 뜨면 줄이세요.

  links.forEach(a => {
    a.addEventListener('click', (e) => {
      const hash = a.getAttribute('href');
      if (!hash || !hash.startsWith('#')) return;

      const target = document.querySelector(hash);
      if (!target) return;

      e.preventDefault();

      const smoother = (window.ScrollSmoother && ScrollSmoother.get) ? ScrollSmoother.get() : null;

      if (smoother) {
        smoother.scrollTo(target, true, `top-=${OFFSET}`);
      } else {
        // smoother 없는 모바일/비PC 대응
        const y = target.getBoundingClientRect().top + window.pageYOffset - OFFSET;
        window.scrollTo({ top: y, behavior: 'smooth' });
      }

      history.pushState(null, '', hash);
    });
  });
})();

// # 포함된 주소로 접속하는 경우 해당 섹션으로 이동
window.addEventListener('load', () => {
  const hash = location.hash;
  if (!hash) return;

  const target = document.querySelector(hash);
  if (!target) return;

  const OFFSET = 100; // 위가 잘리면 조절 (보통 80~120)

  // 브라우저 기본 점프 리셋
  window.scrollTo(0, 0);

  // ScrollSmoother가 있는 경우(PC)
  const smoother = (window.ScrollSmoother && ScrollSmoother.get)
    ? ScrollSmoother.get()
    : null;

  if (smoother) {
    // GSAP 레이아웃 계산 완료 후 이동
    gsap.delayedCall(0.15, () => {
      smoother.scrollTo(target, true, `top-=${OFFSET}`);
    });
  } else {
    // 모바일 / smoother 없는 환경
    const y = target.getBoundingClientRect().top + window.pageYOffset - OFFSET;
    window.scrollTo({ top: y, behavior: 'auto' });
  }
});