JavaScript 없이 CSS만으로 스크롤 애니메이션 구현하기

0

복잡한 JavaScript 라이브러리 없이 단 몇 줄의 CSS 코드만으로 매끄러운 스크롤 애니메이션을 구현할 수 있다면 어떨까요? 2025년 현재, 이것은 더 이상 상상이 아닌 현실입니다. Safari 26 베타를 시작으로 주요 브라우저들이 CSS 스크롤 기반 애니메이션을 지원하면서, 웹 개발의 새로운 가능성이 열리고 있습니다.

왜 CSS 스크롤 애니메이션이 중요한가?

웹 개발자라면 누구나 한 번쯤 경험했을 것입니다. 멋진 스크롤 효과를 구현하기 위해 무거운 라이브러리를 설치하고, 복잡한 JavaScript 코드와 씨름하며, 성능 최적화로 밤을 지새웠던 경험 말입니다. 특히 모바일 환경에서는 JavaScript 기반 스크롤 애니메이션이 배터리를 급격히 소모시키고 프레임 드롭을 야기하는 문제가 빈번했습니다.

그러나 CSS Animations Level 2 사양에 포함된 animation-timeline 속성의 등장으로 이 모든 것이 변했습니다. 이제 브라우저 네이티브 기능만으로도 부드럽고 성능 좋은 스크롤 애니메이션을 구현할 수 있게 된 것입니다. JavaScript 라이브러리 의존성이 줄어들면서 번들 크기가 작아지고, GPU 가속을 활용한 최적화된 렌더링으로 배터리 효율도 개선되었습니다.

스크롤 기반 애니메이션의 핵심 구조

CSS 스크롤 애니메이션을 제대로 활용하려면 세 가지 핵심 요소를 이해해야 합니다.

타겟(Target)은 애니메이션을 적용할 페이지 내 요소입니다. 이미지, 텍스트, 진행바 등 어떤 HTML 요소든 타겟이 될 수 있습니다. 키프레임(Keyframes)은 사용자가 스크롤할 때 요소에 일어나는 시각적 변화를 정의합니다. 기존 CSS 애니메이션과 동일한 @keyframes 문법을 사용하므로 별도의 학습 곡선이 없습니다.

가장 중요한 것은 타임라인(Timeline)입니다. 기존 CSS 애니메이션은 시간을 기준으로 진행되었지만, 스크롤 기반 애니메이션은 사용자의 스크롤 위치를 타임라인으로 사용합니다. 이것이 바로 animation-timeline 속성이 하는 역할입니다.

실전 예제 1: 페이지 진행률 표시 바 만들기

가장 직관적인 예시로 페이지 하단에 스크롤 진행률을 표시하는 진행바를 구현해보겠습니다.

먼저 타겟 요소를 생성합니다:

footer::after {
  content: "";
  height: 1em;
  width: 100%;
  background: rgba(254, 178, 16, 1);
  left: 0;
  bottom: 0;
  position: fixed;
}

페이지 하단에 고정된 노란색 막대가 만들어졌습니다. 이제 키프레임을 정의합니다:

@keyframes progress-expand {
  from { width: 0%; }
  to { width: 100%; }
}

마지막으로 스크롤 타임라인을 적용합니다:

footer::after {
  animation: progress-expand;
  animation-timeline: scroll();
}

여기서 핵심은 animation-timeline: scroll() 속성입니다. 이 한 줄로 애니메이션이 시간이 아닌 스크롤 위치에 따라 진행됩니다. 사용자가 페이지를 스크롤할수록 진행바가 0%에서 100%로 자연스럽게 확장됩니다.

중요한 주의사항이 있습니다. animation-timeline 속성은 반드시 animation 속성 뒤에 선언해야 합니다. CSS의 단축 속성인 animation이 개별 속성들을 초기화하기 때문에, 순서가 바뀌면 animation-timeline 설정이 무시됩니다.

CSS 스크롤 타임라인 애니메이션

실전 예제 2: 요소 등장 효과 with view() 타임라인

두 번째로 살펴볼 view() 타임라인은 특정 요소가 뷰포트에 들어올 때 애니메이션을 실행합니다. 이미지가 화면에 나타날 때 오른쪽에서 슬라이드하며 등장하는 효과를 만들어보겠습니다.

@keyframes slideIn {
  0% {
    transform: translateX(100%);
    opacity: 0;
  }
  100% {
    transform: translateX(0%);
    opacity: 1;
  }
}

img {
  animation: slideIn;
  animation-timeline: view();
}
CSS 슬라이드 애니메이션 1

이렇게 하면 이미지가 뷰포트에 들어올 때마다 오른쪽에서 부드럽게 슬라이드하며 나타납니다. 하지만 기본 설정에서는 이미지가 화면에 있는 내내 계속 움직이는 문제가 있습니다.

이를 해결하는 것이 animation-range 속성입니다:

img {
  animation: slideIn;
  animation-timeline: view();
  animation-range: 0% 50%;
}
CSS 슬라이드 애니메이션 2

이제 이미지가 뷰포트의 절반 지점에 도달하면 애니메이션이 완료되고, 그 자리에 안정적으로 머무릅니다. 사용자 경험이 훨씬 자연스러워집니다.

웹 접근성: 모든 사용자를 배려하는 구현

화려한 애니메이션도 중요하지만, 모든 사용자가 편안하게 이용할 수 있어야 합니다. 일부 사용자는 전정기관 장애나 시각적 민감성으로 인해 움직이는 콘텐츠에 불편함을 느낄 수 있습니다.

이를 위해 prefers-reduced-motion 미디어 쿼리를 활용해야 합니다:

@media not (prefers-reduced-motion) {
  img {
    animation: slideIn;
    animation-timeline: view();
    animation-range: 0% 50%;
  }
}

이렇게 하면 운영체제나 브라우저에서 ‘애니메이션 동작 줄이기’ 설정을 활성화한 사용자에게는 애니메이션이 적용되지 않습니다. 접근성을 고려한 웹 개발은 선택이 아닌 필수입니다.

고급 제어: 매개변수로 세밀하게 조정하기

scroll()view() 함수는 다양한 매개변수를 받아 더욱 정교한 제어가 가능합니다.

스크롤러 요소 지정:

  • nearest (기본값): 가장 가까운 스크롤 가능한 상위 요소를 기준으로 합니다
  • root: 문서의 루트 스크롤러를 사용합니다
  • self: 요소 자기 자신의 스크롤을 기준으로 합니다

스크롤 축 지정:

  • block (기본값): 세로 스크롤에 반응합니다
  • inline: 가로 스크롤에 반응합니다
  • x, y: 명시적으로 축을 지정합니다

예를 들어, 가로 스크롤에 반응하는 애니메이션을 만들고 싶다면:

.element {
  animation: slideIn;
  animation-timeline: scroll(inline);
}

실전 프로젝트 도입 전략

CSS 스크롤 애니메이션을 실제 프로젝트에 도입할 때는 몇 가지를 고려해야 합니다.

성능 최적화 측면에서 GPU 가속을 활용하는 transform 속성을 우선적으로 사용하고, opacity 변화를 활용하면 리페인트 없이 효율적인 애니메이션을 구현할 수 있습니다. 다만 과도한 애니메이션은 여전히 배터리 소모를 증가시킬 수 있으므로 적절한 균형이 필요합니다.

브라우저 지원 현황은 2025년 11월 기준 Safari 26 베타에서 지원되고 있으며, Chrome과 Firefox도 순차적으로 지원을 확대하고 있습니다. Can I Use 웹사이트에서 최신 지원 현황을 확인할 수 있습니다.

점진적 개선(Progressive Enhancement) 전략을 활용하면 안전합니다:

/* 기본 스타일 - 모든 브라우저 */
.element {
  opacity: 1;
  transform: translateX(0);
}

/* 스크롤 애니메이션 지원 브라우저 */
@supports (animation-timeline: scroll()) {
  .element {
    animation: slideIn;
    animation-timeline: view();
  }
}

이렇게 하면 지원하지 않는 브라우저에서도 기본 스타일이 정상적으로 표시되면서, 지원하는 브라우저에서는 향상된 경험을 제공할 수 있습니다.

웹 개발의 새로운 지평

CSS 스크롤 애니메이션은 단순한 기술적 진보를 넘어, 웹 개발 패러다임의 중요한 변화를 의미합니다. JavaScript에 의존하지 않고도 복잡한 인터랙션을 구현할 수 있게 되면서, 개발자들은 더 가볍고 성능 좋은 웹사이트를 만들 수 있게 되었습니다.

특히 모바일 환경에서의 개선은 주목할 만합니다. 네이티브 CSS 애니메이션은 JavaScript 기반 솔루션보다 배터리 효율이 뛰어나며, 스크롤 이벤트 리스너를 등록하지 않아도 되므로 메인 스레드 부하도 줄어듭니다.

2007년 애플이 웹에 CSS 애니메이션을 처음 도입한 지 18년, 이제 우리는 CSS만으로도 JavaScript 라이브러리 못지않은 풍부한 인터랙션을 구현할 수 있는 시대에 살고 있습니다. 앞으로는 더욱 다양한 타임라인과 애니메이션 속성이 추가될 것으로 예상됩니다.

여러분의 다음 프로젝트에서 CSS 스크롤 애니메이션을 활용해보세요. 사용자들에게 더 부드럽고 인상적인 경험을 선사할 수 있을 것입니다.

참고 자료: WebKit Blog, “A Guide to Scroll-driven Animations with just CSS”

답글 남기기