CSS 스크롤 기반 애니메이션: 자바스크립트 불필요

발행: (2026년 5월 26일 AM 08:14 GMT+9)
7 분 소요
원문: Dev.to

출처: Dev.to

CSS 스크롤 기반 애니메이션: 자바스크립트 없이도 가능 커버 이미지

페이지에 스크롤 진행 바를 추가하거나 “스크롤 시 나타내기” 효과를 만든 적이 있다면, 아마도 Intersection Observer, 스크롤 이벤트 리스너, 혹은 GSAP 같은 라이브러리를 사용했을 것입니다. 이러한 방법도 동작하지만 메인 스레드에서 실행되고 번들 용량을 늘리며, 종종 정교한 정리 작업이 필요합니다. CSS 스크롤‑드리븐 애니메이션을 사용하면 자바스크립트 없이도 CSS 애니메이션을 스크롤 위치에 직접 연결할 수 있습니다. 그 결과 메인 스레드가 바쁘더라도 컴포지터 스레드에서 부드럽게 실행되는 애니메이션을 얻을 수 있습니다.

두 가지 타임라인 유형

API의 핵심은 animation-timeline 속성으로, 기본 시간 기반 애니메이션 타임라인을 스크롤 기반 타임라인으로 교체합니다. 두 가지 형태가 있습니다: scroll()view().

scroll()

스크롤 컨테이너가 위쪽(0 %)부터 아래쪽(100 %)까지 얼마나 스크롤됐는지를 추적합니다. 문서 전체 스크롤 진행 상황을 반영해야 하는 경우, 예를 들어 읽기 진행 바와 같은 상황에 이상적입니다.

@keyframes grow-bar {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: oklch(60% 0.2 250);
  transform-origin: left;

  animation: grow-bar linear;
  animation-timeline: scroll(root block);
  animation-fill-mode: both;
}

scroll(root block) 은 브라우저에게 루트 스크롤 컨테이너의 블록(수직) 축을 타임라인으로 사용하도록 지시합니다. 스크롤 리스너도 requestAnimationFrame도 필요 없으며, 브라우저가 전적으로 컴포지터 레벨에서 처리합니다.

view()

요소가 스크롤 컨테이너 안에서 뷰포트에 들어오고 나갈 때의 가시성을 추적합니다. 각 카드나 섹션이 화면에 들어올 때 애니메이션을 적용하는 “reveal” 효과에 특화되어 있습니다.

@keyframes fade-up {
  from {
    opacity: 0;
    translate: 0 40px;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}

.card {
  animation: fade-up linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 40%;
}

animation-range 속성을 사용하면 요소가 뷰포트를 통과하는 과정 중 어느 구간에서 애니메이션을 구동할지 지정할 수 있습니다. entry 0% entry 40% 은 “요소가 뷰포트에 처음 들어오는 40 % 구간 동안 애니메이션을 실행한다”는 의미이며, 요소가 화면에 완전히 나타나기 전에 깔끔한 reveal 효과를 제공합니다.

스크롤 트리거 애니메이션 (Chrome 145+)

새로운 기능: 스크롤‑트리거 애니메이션. 스크롤‑드리븐 애니메이션이 위치에 따라 지속적으로 업데이트되는 것과 달리, 스크롤‑트리거 애니메이션은 스크롤 임계값을 넘을 때 한 번만 실행됩니다—IntersectionObserver와 비슷하지만 CSS만으로 선언적으로 구현됩니다.

@keyframes highlight-nav {
  to {
    background: oklch(25% 0 0);
    box-shadow: 0 2px 12px oklch(0% 0 0 / 30%);
  }
}

header {
  animation: highlight-nav linear forwards;
  animation-timeline: scroll(root);
  animation-range: 80px 81px;
}

사용자가 80 px 이상 스크롤하면 헤더 배경이 바뀌고 그 상태를 유지합니다. 기존의 sticky‑nav‑scroll‑listener 패턴을 한 줄로 대체할 수 있습니다.

점진적 향상

브라우저 지원은 대체로 양호하지만 완전하지는 않습니다—Firefox는 아직 플래그 뒤에 부분 지원만 제공합니다. 스크롤‑드리븐 애니메이션을 @supports 검사로 감싸서 경험이 부드럽게 낮아지도록 하세요.

@supports (animation-timeline: scroll()) {
  .progress-bar {
    animation: grow-bar linear;
    animation-timeline: scroll(root block);
    animation-fill-mode: both;
  }
}

@supports 가드가 없으면 animation-timeline 을 이해하지 못하는 브라우저는 해당 선언을 무시합니다. UI 요소가 필수가 아니라면 괜찮습니다—깨진 바보다 아예 없는 바가 낫습니다. 중요한 reveal 애니메이션이라면 기본적으로 요소가 보이도록 하고, 해당 기능이 지원될 때만 애니메이션을 적용하도록 하세요.

언제 사용해야 할까

스크롤‑드리븐 애니메이션은 효과가 순수히 시각적이며 스크롤 위치와 직접 연결될 때 빛을 발합니다: 읽기 진행 표시, 스티키 헤더 전환, 패럴랙스 배경, 요소 reveal, 이미지 캐러셀 등. 상태 업데이트, 데이터 가져오기, 분석 이벤트와 같은 부수

0 조회
Back to Blog

관련 글

더 보기 »

HTML-in-Canvas 데모

This is a collection of resources to help developers build with HTML‑in‑Canvas. Check out the HTML‑in‑Canvas demo deployed at or view the source code on GitHub:...