스크롤 기반 애니메이션으로 스크롤 시 요소에 애니메이션 적용

스크롤 타임라인과 뷰 타임라인을 사용하여 선언적 방식으로 스크롤 기반 애니메이션을 만드는 방법을 알아보세요.

스크롤 기반 애니메이션

브라우저 지원

  • Chrome: 115.
  • Edge: 115.
  • Firefox: 플래그 뒤에 있습니다.
  • Safari: 지원되지 않음

소스

스크롤 기반 애니메이션은 웹에서 일반적인 UX 패턴입니다. 스크롤 기반 애니메이션은 스크롤 컨테이너의 스크롤 위치와 연결됩니다. 즉, 위 또는 아래로 스크롤하면 연결된 애니메이션이 직접적으로 앞뒤로 스크러빙됩니다. 스크롤할 때 움직이는 시차 배경 이미지 또는 읽기 표시기와 같은 효과가 여기에 해당합니다.

스크롤에 의해 구동되는 문서 상단의 읽기 표시기입니다.

스크롤 기반 애니메이션의 유사한 유형은 스크롤 컨테이너 내의 요소 위치에 연결된 애니메이션입니다. 예를 들어 이를 사용하면 요소가 표시될 때 페이드 인할 수 있습니다.

이 페이지의 이미지가 표시될 때 페이드 인됩니다.

이러한 종류의 효과를 얻는 일반적인 방법은 기본 스레드에서 스크롤 이벤트에 응답하는 것이지만, 이 경우 다음과 같은 두 가지 주요 문제가 발생합니다.

  • 최신 브라우저는 별도의 프로세스에서 스크롤을 실행하므로 스크롤 이벤트를 비동기식으로 전송합니다.
  • 기본 스레드 애니메이션에 버벅거림이 발생할 수 있습니다.

따라서 스크롤과 동기화되는 성능이 우수한 스크롤 기반 애니메이션을 만들기가 불가능하거나 매우 어렵습니다.

Chrome 버전 115부터 선언적 스크롤 기반 애니메이션을 사용 설정하는 데 사용할 수 있는 새로운 API 및 개념인 Scroll Timelines 및 View Timelines가 있습니다.

이러한 새로운 개념은 기존 Web Animations API (WAAPI)CSS Animations API와 통합되어 기존 API의 이점을 상속할 수 있습니다. 여기에는 스크롤 기반 애니메이션이 기본 스레드 밖에서 실행되도록 하는 기능이 포함됩니다. 예, 맞습니다. 이제 코드 몇 줄만 추가하면 스크롤에 의해 구동되고 기본 스레드에서 실행되는 부드럽고 매끄러운 애니메이션을 만들 수 있습니다. 마음에 들지 않는 점이 뭐지?!

웹에서의 애니메이션, 간단한 요약

CSS를 사용한 웹 애니메이션

CSS에서 애니메이션을 만들려면 @keyframes at-rule을 사용하여 키프레임 세트를 정의합니다. animation-name 속성을 사용하여 요소에 연결하는 동시에 animation-duration를 설정하여 애니메이션 재생 시간을 결정합니다. animation-*의 긴 속성(animation-easing-function, animation-fill-mode 등)이 더 많이 있으며 모두 animation 약어로 결합할 수 있습니다.

예를 들어 다음은 X축의 요소 크기를 조절하면서 배경 색상을 변경하는 애니메이션입니다.

@keyframes scale-up {
  from {
    background-color: red;
    transform: scaleX(0);
  }
  to {
    background-color: darkred;
    transform: scaleX(1);
  }
}

#progressbar {
  animation: 2.5s linear forwards scale-up;
}
를 참고하세요.

JavaScript를 사용한 웹 애니메이션

JavaScript에서는 Web Animations API를 사용하여 정확히 동일한 작업을 실행할 수 있습니다. 새 AnimationKeyFrameEffect 인스턴스를 만들거나 훨씬 더 짧은 Element animate() 메서드를 사용하면 됩니다.

document.querySelector('#progressbar').animate(
  {
    backgroundColor: ['red', 'darkred'],
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    duration: 2500,
    fill: 'forwards',
    easing: 'linear',
   }
);

위 자바스크립트 스니펫의 시각적 결과는 이전 CSS 버전과 동일합니다.

애니메이션 타임라인

기본적으로 요소에 연결된 애니메이션은 문서 타임라인에서 실행됩니다. 출발 시간은 페이지가 로드될 때 0으로 시작하고 시계 시간이 지남에 따라 앞으로 전진합니다. 이것이 기본 애니메이션 타임라인이며 지금까지 액세스할 수 있었던 유일한 애니메이션 타임라인이었습니다.

스크롤 기반 애니메이션 사양은 사용할 수 있는 두 가지 새로운 유형의 타임라인을 정의합니다.

  • 스크롤 진행률 타임라인: 특정 축을 따라 스크롤 컨테이너의 스크롤 위치에 연결된 타임라인입니다.
  • 뷰 진행률 타임라인: 스크롤 컨테이너 내 특정 요소의 상대 위치에 연결된 타임라인입니다.

스크롤 진행률 타임라인

스크롤 진행률 타임라인은 특정 축을 따라 스크롤 컨테이너(스크롤 포트 또는 스크롤러라고도 함)의 스크롤 위치에서 진행률에 링크된 애니메이션 타임라인입니다. 스크롤 범위의 위치를 진행률(%)로 변환합니다.

시작 스크롤 위치는 0% 진행률로 나타내고 종료 스크롤 위치는 100% 진행률로 나타냅니다. 다음 시각화에서 스크롤러를 위에서 아래로 스크롤하면 진행률이 0% 에서 100% 까지 증가하는 것을 볼 수 있습니다.

스크롤 진행률 타임라인의 시각화입니다. 스크롤러 하단으로 아래로 스크롤하면 진행률 값이 0% 에서 100%까지 증가합니다.

✨ 직접 사용해 보기

스크롤 진행률 타임라인은 '스크롤 타임라인'으로 줄여서 부르는 경우가 많습니다.

뷰 진행률 타임라인

이 유형의 타임라인은 스크롤 컨테이너 내 특정 요소의 상대적인 진행률에 링크됩니다. 스크롤 진행률 타임라인과 마찬가지로 스크롤러의 스크롤 오프셋이 추적됩니다. 스크롤 진행률 타임라인과 달리 진행률을 결정하는 것은 해당 스크롤러 내에서 대상의 상대 위치입니다.

이는 스크롤러에 요소가 표시되는 양을 추적할 수 있는 IntersectionObserver의 작동 방식과 다소 비슷합니다. 스크롤러에 요소가 보이지 않으면 교차하지 않습니다. 가장 작은 부분이라도 스크롤러 내부에 보이면 교차합니다.

뷰 진행률 타임라인은 대상이 스크롤러와 교차하기 시작하는 순간부터 시작되어 대상이 스크롤러와 교차하는 것을 멈출 때 끝납니다. 다음 시각화에서 진행률은 대상이 스크롤 컨테이너에 들어갈 때 0% 부터 시작하여 대상이 스크롤 컨테이너를 벗어날 때 100% 에 도달하는 것을 볼 수 있습니다.

뷰 진행률 타임라인의 시각화 대상 (녹색 상자)이 스크롤러를 넘어가면 진행률이 0% 에서 100% 까지 올라갑니다.

✨ 직접 사용해 보기

뷰 진행률 타임라인은 '뷰 타임라인'으로 줄여서 부르는 경우가 많습니다. 피사체의 크기를 기준으로 뷰 타임라인의 특정 부분을 타겟팅할 수 있지만 자세한 내용은 나중에 설명합니다.

스크롤 진행률 타임라인을 활용한 실용적인 방법

CSS에서 익명의 스크롤 진행률 타임라인 만들기

CSS에서 스크롤 타임라인을 만드는 가장 쉬운 방법은 scroll() 함수를 사용하는 것입니다. 이 함수를 사용하면 새 animation-timeline 속성의 값으로 설정할 수 있는 익명의 스크롤 타임라인이 생성됩니다.

예:

@keyframes animate-it {  }

.subject {
  animation: animate-it linear;
  animation-timeline: scroll(root block);
}

scroll() 함수는 <scroller><axis> 인수를 허용합니다.

<scroller> 인수에 허용되는 값은 다음과 같습니다.

  • nearest: 가장 가까운 상위 스크롤 컨테이너를 사용합니다(기본값).
  • root: 문서 표시 영역을 스크롤 컨테이너로 사용합니다.
  • self: 요소 자체를 스크롤 컨테이너로 사용합니다.

<axis> 인수에 허용되는 값은 다음과 같습니다.

  • block: 스크롤 컨테이너의 블록 축을 따라 진행률 측정을 사용합니다(기본값).
  • inline: 스크롤 컨테이너의 인라인 축을 따라 진행률 측정을 사용합니다.
  • y: 스크롤 컨테이너의 Y축을 따라 진행률 측정을 사용합니다.
  • x: 스크롤 컨테이너의 X축을 따라 진행률 측정을 사용합니다.

예를 들어 애니메이션을 블록 축의 루트 스크롤러에 바인딩하려면 scroll()에 전달할 값이 rootblock입니다. 합산된 값은 scroll(root block)입니다.

데모: 독서 진행률 표시기

이 데모에는 표시 영역 상단에 고정된 읽기 진행률 표시기가 있습니다. 페이지를 아래로 스크롤하면 진행률 표시줄이 커지면서 문서의 끝에 도달하면 전체 표시 영역 너비를 차지하게 됩니다. 익명의 스크롤 진행률 타임라인은 애니메이션을 구동하는 데 사용됩니다.

데모: 읽기 진행률 표시기

✨ 직접 사용해 보기

읽기 진행률 표시기는 고정된 위치를 사용하여 페이지 상단에 배치됩니다. 합성 애니메이션을 활용하려면 width가 애니메이션되지 않고 요소가 transform를 사용하여 x축에서 축소됩니다.

<body>
  <div id="progress"></div>
  …
</body>
@keyframes grow-progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

#progress {
  position: fixed;
  left: 0; top: 0;
  width: 100%; height: 1em;
  background: red;

  transform-origin: 0 50%;
  animation: grow-progress auto linear;
  animation-timeline: scroll();
}

#progress 요소의 애니메이션 grow-progress의 타임라인은 scroll()를 사용하여 생성된 익명의 타임라인으로 설정됩니다. scroll()에 인수가 제공되지 않으므로 기본값으로 대체됩니다.

추적할 기본 스크롤러는 nearest이고 기본 축은 block입니다. 이렇게 하면 #progress 요소에 가장 가까운 스크롤러이므로 루트 스크롤러를 효과적으로 타겟팅하면서 블록 방향을 추적할 수 있습니다.

CSS에서 이름이 지정된 스크롤 진행률 타임라인 만들기

스크롤 진행률 타임라인을 정의하는 다른 방법은 이름이 지정된 스크롤 진행률 타임라인을 사용하는 것입니다. 좀 더 세부적이지만 상위 스크롤러 또는 루트 스크롤러를 타겟팅하지 않거나 페이지에서 여러 타임라인을 사용할 때 또는 자동 조회가 작동하지 않을 때 이 방법이 유용할 수 있습니다. 이렇게 하면 이름을 지정하여 스크롤 진행률 타임라인을 식별할 수 있습니다.

요소에 대해 이름이 지정된 스크롤 진행률 타임라인을 만들려면 스크롤 컨테이너의 scroll-timeline-name CSS 속성을 원하는 식별자로 설정합니다. 값은 --로 시작해야 합니다.

추적할 축을 조정하려면 scroll-timeline-axis 속성도 선언합니다. 허용되는 값은 scroll()<axis> 인수와 동일합니다.

마지막으로 애니메이션을 스크롤 진행률 타임라인에 링크하려면 애니메이션을 적용해야 하는 요소의 animation-timeline 속성을 scroll-timeline-name에 사용된 식별자와 동일한 값으로 설정합니다.

코드 예시:

@keyframes animate-it {  }

.scroller {
  scroll-timeline-name: --my-scroller;
  scroll-timeline-axis: inline;
}

.scroller .subject {
  animation: animate-it linear;
  animation-timeline: --my-scroller;
}

원하는 경우 scroll-timeline 약어에서 scroll-timeline-namescroll-timeline-axis를 결합할 수 있습니다. 예를 들면 다음과 같습니다.

scroll-timeline: --my-scroller inline;

이 데모에서는 각 이미지 캐러셀 위에 단계 표시기가 표시됩니다. 캐러셀에 이미지가 3개 포함되어 있는 경우 표시기의 너비는 33% 로 시작되며 현재 세 개의 이미지 중 하나를 보고 있음을 나타냅니다. 마지막 이미지가 시야에 들어오면(스크롤러가 끝까지 스크롤한 후에 결정) 표시기가 스크롤러의 전체 너비를 차지합니다. 이름이 지정된 스크롤 진행률 타임라인은 애니메이션을 구동하는 데 사용됩니다.

데모: 가로형 캐러셀 단계 표시기

✨ 직접 사용해 보기

갤러리의 기본 마크업은 다음과 같습니다.

<div class="gallery" style="--num-images: 2;">
  <div class="gallery__scrollcontainer">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">…</div>
    <div class="gallery__entry">…</div>
  </div>
</div>

.gallery__progress 요소는 .gallery 래퍼 요소 내에 절대적으로 배치됩니다. 초기 크기는 --num-images 맞춤 속성에 따라 결정됩니다.

.gallery {
  position: relative;
}


.gallery__progress {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 1em;
  transform: scaleX(calc(1 / var(--num-images)));
}

.gallery__scrollcontainer는 포함된 .gallery__entry 요소를 가로로 배치하며 스크롤되는 요소입니다. 스크롤 위치를 추적하여 .gallery__progress에 애니메이션이 적용됩니다. 이름이 지정된 스크롤 진행률 타임라인 --gallery__scrollcontainer을 참조하면 됩니다.

@keyframes grow-progress {
  to { transform: scaleX(1); }
}

.gallery__scrollcontainer {
  overflow-x: scroll;
  scroll-timeline: --gallery__scrollcontainer inline;
}
.gallery__progress {
  animation: auto grow-progress linear forwards;
  animation-timeline: --gallery__scrollcontainer;
}

JavaScript로 스크롤 진행률 타임라인 만들기

JavaScript로 스크롤 타임라인을 만들려면 ScrollTimeline 클래스의 새 인스턴스를 만듭니다. 추적하려는 sourceaxis가 포함된 속성 백을 전달합니다.

  • source: 추적하려는 스크롤러가 있는 요소에 대한 참조입니다. document.documentElement를 사용하여 루트 스크롤러를 타겟팅합니다.
  • axis: 추적할 축을 결정합니다. CSS 변형과 마찬가지로 허용되는 값은 block, inline, x, y입니다.
const tl = new ScrollTimeline({
  source: document.documentElement,
});

웹 애니메이션에 연결하려면 timeline 속성으로 전달하고 duration가 있으면 생략합니다.

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
});

데모: 읽기 진행률 표시기 다시 살펴보기

동일한 마크업을 사용하면서 JavaScript로 독서 진행률 표시기를 다시 만들려면 다음 JavaScript 코드를 사용하세요.

const $progressbar = document.querySelector('#progress');

$progressbar.style.transformOrigin = '0% 50%';
$progressbar.animate(
  {
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    fill: 'forwards',
    timeline: new ScrollTimeline({
      source: document.documentElement,
    }),
  }
);

CSS 버전에서도 시각적 결과는 동일합니다. 생성된 timeline는 루트 스크롤러를 추적하고 페이지를 스크롤할 때 x축에서 #progress를 0% 에서 100% 로 확장합니다.

✨ 직접 사용해 보기

뷰 진행률 타임라인을 활용한 실용적인 방법

CSS에서 익명 뷰 진행률 타임라인 만들기

뷰 진행률 타임라인을 만들려면 view() 함수를 사용합니다. 허용되는 인수는 <axis><view-timeline-inset>입니다.

  • <axis>는 스크롤 진행률 타임라인과 동일하며 추적할 축을 정의합니다. 기본값은 block입니다.
  • <view-timeline-inset>를 사용하면 요소가 시야에 있거나 없는 것으로 간주될 때 경계를 조정하도록 오프셋(양수 또는 음수)을 지정할 수 있습니다. 값은 백분율 또는 auto여야 하며 auto은 기본값입니다.

예를 들어 애니메이션을 블록 축에서 스크롤러와 교차하는 요소에 바인딩하려면 view(block)를 사용합니다. scroll()와 마찬가지로 animation-timeline 속성의 값으로 설정하고 animation-durationauto로 설정해야 합니다.

다음 코드를 사용하면 스크롤하는 동안 뷰포트를 지나갈 때마다 모든 img가 페이드 인됩니다.

@keyframes reveal {
  from { opacity: 0; }
  to { opacity: 1; }
}

img {
  animation: reveal linear;
  animation-timeline: view();
}

인터미즈조: 타임라인 범위 보기

기본적으로 뷰 타임라인에 연결된 애니메이션은 전체 타임라인 범위에 연결됩니다. 이는 대상이 스크롤 포트에 들어가는 순간부터 시작하여 대상이 스크롤 포트를 완전히 벗어났을 때 끝납니다.

연결해야 하는 범위를 지정하여 뷰 타임라인의 특정 부분에 연결할 수도 있습니다. 예를 들어 대상이 스크롤러에 들어갈 때만 가능합니다. 다음 시각화에서 진행률은 대상이 스크롤 컨테이너에 들어갈 때 0%부터 시작하지만 완전히 교차하는 순간부터 이미 100%에 도달합니다.

주제의 항목 범위를 추적하도록 설정된 뷰 타임라인입니다. 애니메이션은 대상이 스크롤 포트에 들어가는 동안에만 실행됩니다.

타겟팅할 수 있는 뷰 타임라인 범위는 다음과 같습니다.

  • cover: 뷰 진행률 타임라인의 전체 범위를 나타냅니다.
  • entry: 주 상자가 뷰 진행률 가시성 범위에 들어가는 범위를 나타냅니다.
  • exit: 주 상자가 뷰 진행률 가시성 범위를 벗어나는 범위를 나타냅니다.
  • entry-crossing: 주 상자가 끝 테두리 가장자리를 교차하는 범위를 나타냅니다.
  • exit-crossing: 주 상자가 시작 테두리 가장자리를 교차하는 범위를 나타냅니다.
  • contain: 주 상자가 스크롤 포트 내의 뷰 진행률 가시성 범위에 완전히 포함되거나 완전히 포함하는 범위를 나타냅니다. 대상이 스크롤러보다 길거나 짧은지에 따라 달라집니다.

범위를 정의하려면 range-start 및 range-end를 설정해야 합니다. 각각은 range-name(위 목록 참고)과 해당 range-name 내의 위치를 결정하는 range-offset으로 구성됩니다. 범위 오프셋은 일반적으로 0%에서 100% 사이의 백분율이지만 20em와 같이 고정된 길이를 지정할 수도 있습니다.

예를 들어 피사체가 들어오는 순간부터 애니메이션을 실행하려면 범위 시작으로 entry 0%를 선택합니다. 주제가 입력될 때까지 완료되도록 하려면 범위 종료 값으로 entry 100%를 선택합니다.

CSS에서는 animation-range 속성을 사용하여 이를 설정합니다. 예:

animation-range: entry 0% entry 100%;

JavaScript에서는 rangeStartrangeEnd 속성을 사용합니다.

$el.animate(
  keyframes,
  {
    timeline: tl,
    rangeStart: 'entry 0%',
    rangeEnd: 'entry 100%',
  }
);

아래에 삽입된 도구를 사용하여 각 범위 이름이 나타내는 항목과 해당 비율이 시작 및 끝 위치에 미치는 영향을 확인하세요. range-start를 entry 0%로, range-end를 cover 50%로 설정한 다음 스크롤바를 드래그하여 애니메이션 결과를 확인해 보세요.

뷰 타임라인 범위 비주얼라이저(https://goo.gle/view-timeline-range-tool에서 사용 가능)

녹화 파일 보기

타임라인 범위 보기 도구를 사용해 보면 알 수 있듯이 일부 범위는 두 가지 다른 range-name + range-offset 조합으로 타겟팅할 수 있습니다. 예를 들어 entry 0%, entry-crossing 0%, cover 0%는 모두 동일한 영역을 타겟팅합니다.

range-start와 range-end가 동일한 range-name을 타겟팅하고 전체 범위(0% ~100%)를 차지하는 경우 값을 범위 이름으로 줄일 수 있습니다. 예를 들어 animation-range: entry 0% entry 100%;는 훨씬 더 짧은 animation-range: entry로 재작성할 수 있습니다.

데모: 이미지 공개

이 데모에서는 이미지가 스크롤 포트에 들어갈 때 이미지가 페이드 인됩니다. 이 작업은 익명 뷰 타임라인을 사용하여 수행됩니다. 각 이미지가 스크롤러의 절반 지점에 있을 때 전체 불투명도가 되도록 애니메이션 범위가 조정되었습니다.

데모: 이미지 공개

✨ 직접 사용해 보기

확장 효과는 애니메이션이 적용된 클립 경로를 사용하여 얻을 수 있습니다. 이 효과에 사용된 CSS는 다음과 같습니다.

@keyframes reveal {
  from { opacity: 0; clip-path: inset(0% 60% 0% 50%); }
  to { opacity: 1; clip-path: inset(0% 0% 0% 0%); }
}

.revealing-image {
  animation: auto linear reveal both;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

CSS에서 이름이 지정된 뷰 진행률 타임라인 만들기

스크롤 타임라인에 이름이 지정된 버전이 있는 것처럼 이름이 지정된 뷰 타임라인을 만들 수도 있습니다. scroll-timeline-* 속성 대신 view-timeline- 접두사가 있는 변형(view-timeline-nameview-timeline-axis)을 사용합니다.

동일한 유형의 값이 적용되며 이름이 지정된 타임라인을 조회하는 데 동일한 규칙이 적용됩니다.

데모: 이미지 공개, 다시 살펴보기

앞의 이미지 공개 데모를 수정하면 수정된 코드는 다음과 같습니다.

.revealing-image {
  view-timeline-name: --revealing-image;
  view-timeline-axis: block;

  animation: auto linear reveal both;
  animation-timeline: --revealing-image;
  animation-range: entry 25% cover 50%;
}

view-timeline-name: revealing-image를 사용하면 가장 가까운 스크롤러 내에서 요소가 추적됩니다. 그러면 동일한 값이 animation-timeline 속성의 값으로 사용됩니다. 시각적 출력은 이전과 정확히 동일합니다.

✨ 직접 사용해 보기

JavaScript에서 뷰 진행률 타임라인 만들기

JavaScript에서 뷰 타임라인을 만들려면 ViewTimeline 클래스의 새 인스턴스를 만듭니다. 추적하려는 subject, axis, inset가 포함된 속성 값을 전달합니다.

  • subject: 자체 스크롤러 내에서 추적하려는 요소에 대한 참조입니다.
  • axis: 추적할 축입니다. CSS 변형과 마찬가지로 허용되는 값은 block, inline, x, y입니다.
  • inset: 상자가 시야에 있는지 확인할 때 스크롤 포트의 인셋 (양수) 또는 아웃셋 (음수) 조정입니다.
const tl = new ViewTimeline({
  subject: document.getElementById('subject'),
});

웹 애니메이션에 연결하려면 timeline 속성으로 전달하고 duration가 있는 경우 생략합니다. 원하는 경우 rangeStartrangeEnd 속성을 사용하여 범위 정보를 전달합니다.

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
  rangeStart: 'entry 25%',
  rangeEnd: 'cover 50%',
});

✨ 직접 사용해 보기

시도해 볼 만한 다른 작업

하나의 키프레임 세트로 여러 뷰 타임라인 범위에 연결

목록 항목에 애니메이션이 적용된 연락처 목록 데모를 살펴보겠습니다. 목록 항목이 하단에서 스크롤 포트에 들어가면 슬라이드+페이딩 인되고, 상단에서 스크롤 포트를 벗어나면 슬라이드+페이딩 아웃됩니다.

데모: 연락처 목록

✨ 직접 사용해 보기

이 데모에서는 각 요소가 스크롤 포트를 지나갈 때 요소를 추적하는 뷰 타임라인 하나로 장식되지만 두 개의 스크롤 기반 애니메이션이 연결됩니다. animate-in 애니메이션은 타임라인의 entry 범위에 연결되고 animate-out 애니메이션은 타임라인의 exit 범위에 연결됩니다.

@keyframes animate-in {
  0% { opacity: 0; transform: translateY(100%); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes animate-out {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-100%); }
}

#list-view li {
  animation: animate-in linear forwards,
             animate-out linear forwards;
  animation-timeline: view();
  animation-range: entry, exit;
}

서로 다른 범위에 연결된 두 개의 서로 다른 애니메이션을 실행하는 대신 범위 정보가 이미 포함된 하나의 키프레임 세트를 만들 수도 있습니다.

@keyframes animate-in-and-out {
  entry 0%  {
    opacity: 0; transform: translateY(100%);
  }
  entry 100%  {
    opacity: 1; transform: translateY(0);
  }
  exit 0% {
    opacity: 1; transform: translateY(0);
  }
  exit 100% {
    opacity: 0; transform: translateY(-100%);
  }
}

#list-view li {
  animation: linear animate-in-and-out;
  animation-timeline: view();
}

키프레임에 범위 정보가 포함되어 있으므로 animation-range를 지정할 필요가 없습니다. 결과는 이전과 정확히 동일합니다.

✨ 직접 사용해 보기

조상 외 스크롤 타임라인에 연결

이름이 지정된 스크롤 타임라인 및 이름이 지정된 뷰 타임라인의 조회 메커니즘은 스크롤 조상만으로 제한됩니다. 그러나 애니메이션으로 표시해야 하는 요소는 추적해야 하는 스크롤러의 하위 요소가 아닌 경우가 매우 많습니다.

이렇게 하려면 timeline-scope 속성이 사용됩니다. 이 속성을 사용하면 실제로 만들지 않고도 해당 이름의 타임라인을 선언할 수 있습니다. 이렇게 하면 해당 이름의 타임라인에 더 넓은 범위가 적용됩니다. 실제로는 하위 스크롤러의 타임라인이 공유 상위 요소에 연결될 수 있도록 공유 상위 요소에서 timeline-scope 속성을 사용합니다.

예를 들면 다음과 같습니다.

.parent {
  timeline-scope: --tl;
}
.parent .scroller {
  scroll-timeline: --tl;
}
.parent .scroller ~ .subject {
  animation: animate linear;
  animation-timeline: --tl;
}

이 스니펫에서는 다음 사항이 적용됩니다.

  • .parent 요소는 이름이 --tl인 타임라인을 선언합니다. 모든 하위 요소는 이 속성을 찾아 animation-timeline 속성의 값으로 사용할 수 있습니다.
  • .scroller 요소는 실제로 --tl라는 이름의 스크롤 타임라인을 정의합니다. 기본적으로 하위 요소에만 표시되지만 .parentscroll-timeline-root로 설정되어 있으므로 scroll-timeline-root에 연결됩니다.
  • .subject 요소는 --tl 타임라인을 사용합니다. 조상 트리를 위로 이동하여 .parent에서 --tl를 찾습니다. .parent--tl.scroller--tl를 가리키면 .subject는 기본적으로 .scroller의 스크롤 진행률 타임라인을 추적합니다.

다시 말해 timeline-root를 사용하여 타임라인을 조상까지 이동 (호이스팅이라고 함)하여 조상의 모든 하위 요소가 액세스할 수 있도록 할 수 있습니다.

timeline-scope 속성은 스크롤 타임라인과 뷰 타임라인 모두에서 사용할 수 있습니다.

추가 데모 및 리소스

스크롤 기반 애니메이션 스타일 미니 사이트에 관한 이 도움말에서 다루는 모든 데모 웹사이트에는 스크롤 기반 애니메이션으로 할 수 있는 작업을 보여주는 더 많은 데모가 포함되어 있습니다.

추가 데모 중 하나는 앨범 커버 목록입니다. 각 커버는 중앙 스포트라이트를 받으면 3D로 회전합니다.

데모: 커버 플로우

✨ 직접 사용해 보기

또는 position: sticky를 활용하는 카드 쌓기 데모를 참고하세요. 카드가 쌓이면 이미 고정된 카드가 축소되어 멋진 깊이 효과를 만듭니다. 마지막으로 전체 비슷한 사진이 그룹으로 화면 밖으로 나갑니다.

데모: 카드 쌓기.

✨ 직접 사용해 보기

또한 scroll-driven-animations.style에는 이 게시물 앞부분에 포함된 뷰 타임라인 범위 진행률 시각화와 같은 도구 모음이 있습니다.

스크롤 기반 애니메이션은 Google I/O 2023의 웹 애니메이션의 새로운 기능에서도 다룹니다.