피닝

Pinning

한 섹션을 화면에 고정해두고, 사용자가 계속 스크롤하는 동안 그 안의 콘텐츠만 진행시키는 기법. 스크롤텔링에서 "한 화면에 머물며 여러 단계를 보여줄 때" 씁니다.

다른 이름: Section pinningScroll pinSticky scrollytelling
···
html
<div class="page" id="page">
  <div class="pin">
    <span class="tag">PINNED</span>
    <div class="steps" id="steps">
      <div class="step">1<b>Intro</b></div>
      <div class="step">2<b>Detail</b></div>
      <div class="step">3<b>Compare</b></div>
      <div class="step">4<b>Done</b></div>
    </div>
    <div class="dots" id="dots"><i></i><i></i><i></i><i></i></div>
  </div>
</div>
css
.page{position:absolute;inset:0;overflow:hidden}
.pin{position:absolute;inset:8% 10%;border:1px solid var(--line);border-radius:14px;background:var(--surface);overflow:hidden;display:flex;flex-direction:column}
.tag{position:absolute;top:8px;left:12px;font:700 9px/1 ui-monospace,monospace;letter-spacing:.08em;color:var(--accent-3);z-index:2}
.steps{position:relative;flex:1;display:flex;width:400%}
.step{flex:none;width:25%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;
  font:800 clamp(26px,9vmin,44px)/1 sans-serif;color:var(--accent)}
.step b{font:600 12px/1 sans-serif;color:var(--muted)}
.dots{display:flex;justify-content:center;gap:8px;padding:10px}
.dots i{width:7px;height:7px;border-radius:50%;background:var(--line)}
.dots i.on{background:var(--accent)}
js
const steps = document.getElementById('steps');
const dots = [...document.getElementById('dots').children];
let i = 0;
function render() {
  steps.style.transform = 'translateX(-' + (i * 25) + '%)';
  dots.forEach((d, idx) => d.classList.toggle('on', idx === i));
}
render();
setInterval(() => {
  i = (i + 1) % 4;
  render();
}, 1400);

보통 스크롤은 페이지 콘텐츠를 위로 흘려보내지만, 피닝은 특정 구간에서 그 흐름을 잠시 멈춥니다. position: sticky(짧은 구간)나 JS로 요소를 position: fixed로 바꾸고 그 구간만큼 페이지에 여분의 스크롤 높이를 미리 확보해두는 방식(긴 구간, 여러 단계)으로 구현합니다. 사용자 입장에서는 스크롤 휠을 계속 돌리는데 화면은 그대로고, 그 안의 그림이나 텍스트만 다음 단계로 넘어갑니다.

핀 구간의 길이는 "그 안에서 보여줄 단계 수 × 한 단계당 필요한 스크롤량"으로 정합니다 — 예를 들어 4단계를 보여주려면 뷰포트 높이의 4배 정도를 여분 스크롤 공간으로 잡고, 그 안의 진행률(0~1)을 스크롤 스크럽처럼 각 단계에 매핑합니다. GSAP ScrollTrigger의 pin: true 옵션이 이 패턴을 널리 알렸습니다.

핀 구간이 너무 길면 사용자가 "스크롤이 안 먹는다"고 느끼고 이탈합니다. 보통 3~5단계, 뷰포트 3~5배 이내로 제한하고, 빠져나갈 수 있는 시각적 신호(다음 섹션이 살짝 보이는 것)를 남겨두는 게 안전합니다.

언제 쓰나

한 화면에서 여러 단계를 순서대로 설명해야 할 때(제품 기능 소개, 데이터 스토리) 씁니다. 단순히 "요소 하나가 등장"하는 정도면 스크롤 리빌로 충분하고 피닝은 과합니다.