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

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

스크롤 기반 애니메이션

브라우저 지원

  • 115
  • 115
  • x

소스

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

문서 상단의 읽기 표시기로, 스크롤로 구동됩니다.

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

이 페이지의 이미지가 페이드 인됩니다.

이러한 종류의 효과를 달성하는 기본적인 방법은 기본 스레드의 스크롤 이벤트에 응답하는 것입니다. 이로 인해 다음과 같은 두 가지 주요 문제가 발생합니다.

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

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

Chrome 버전 115부터 선언적 스크롤 기반 애니메이션을 사용 설정하는 데 사용할 수 있는 새로운 API 및 개념 모음(스크롤 타임라인 및 뷰 타임라인)이 추가되었습니다.

이 새로운 개념은 기존 Web Animations API (WAAPI)CSS Animations API와 통합되어 기존 API의 이점을 상속할 수 있습니다. 여기에는 스크롤 기반 애니메이션을 기본 스레드 외부에서 실행할 수 있는 기능이 포함됩니다. 예, 올바르게 읽어 보세요. 이제 단 몇 줄의 추가 코드만으로 스크롤로 구동되고 기본 스레드에서 실행되고 매끄러운 애니메이션을 만들 수 있습니다. 마음에 들지 않는 것은 무엇인가요?

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

CSS를 사용한 웹 애니메이션

CSS에서 애니메이션을 만들려면 @keyframes at-rule을 사용하여 키프레임 세트를 정의합니다. animation-name 속성을 사용하여 요소에 연결하는 동시에 animation-duration를 설정하여 애니메이션에 걸리는 시간을 결정합니다. 더 많은 animation-* 긴 속성(예: animation-easing-functionanimation-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',
   }
);

위의 JavaScript 스니펫의 이러한 시각적 결과는 이전 CSS 버전과 동일합니다.

애니메이션 타임라인

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

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

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

스크롤 진행률 타임라인

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

시작 스크롤 위치는 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% 너비에서 시작되어 현재 이미지 3개 중 1개를 보고 있음을 나타냅니다. 마지막 이미지가 표시되면(스크롤러가 끝까지 스크롤한 것으로 확인됨) 표시기는 스크롤러의 전체 너비를 차지합니다. 이름이 지정된 스크롤 진행률 타임라인은 애니메이션을 구동하는 데 사용됩니다.

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

✨ 직접 사용해 보기

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

<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로 스크롤 진행률 타임라인 만들기

자바스크립트에서 스크롤 타임라인을 만들려면 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();
}

Intermezzo: 타임라인 범위 보기

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

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

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

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

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

범위를 정의하려면 범위 시작 및 범위 끝을 설정해야 합니다. 각 범위는 범위 이름(위 목록 참조)과 해당 범위 이름 내 위치를 결정하는 범위 오프셋으로 구성됩니다. 범위 오프셋은 일반적으로 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%',
  }
);

아래에 포함된 도구를 사용하여 각 범위-이름이 나타내는 내용과 백분율이 시작 및 종료 위치에 미치는 영향을 확인하세요. 범위 시작을 entry 0%로, 범위 끝을 cover 50%로 설정한 다음 스크롤바를 드래그하여 애니메이션 결과를 확인합니다.

뷰 타임라인 범위 비주얼라이저, https://goo.gle/view-timeline-range-tool에서 제공

녹화 파일 보기

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

범위 시작 및 범위 끝 타겟이 동일한 범위 이름을 지정하고 전체 범위(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인 스크롤 타임라인을 정의합니다. 기본적으로 하위 요소에만 표시되지만 .parent에서 scroll-timeline-root로 설정되어 있으므로 하위 요소에 연결됩니다.
  • .subject 요소는 --tl 타임라인을 사용합니다. 상위 트리를 탐색하여 .parent에서 --tl를 찾습니다. .parent--tl.scroller--tl를 가리키면 .subject는 기본적으로 .scroller의 스크롤 진행률 타임라인을 추적합니다.

달리 말하면, timeline-root를 사용하여 타임라인을 상위 요소로 이동 (호이스팅이라고도 함)하여 상위 항목의 모든 하위 요소가 액세스할 수 있도록 할 수 있습니다.

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

데모 및 리소스 더보기

이 도움말에서 다룬 모든 데모는 scroll-driven-animations.style 미니 사이트에 있습니다. 이 웹사이트에는 스크롤 기반 애니메이션으로 가능한 작업을 강조하는 더 많은 데모가 있습니다.

앨범 표지 목록을 예로 들 수 있습니다. 가운데 스포트라이트를 차지하면 각 표지가 3D로 회전합니다.

데모: 커버 흐름

✨ 직접 사용해 보기

또는 position: sticky를 활용하는 이 스태킹 카드 데모입니다. 쌓여 있는 카드가 쌓이면 쌓여 있는 카드가 점점 줄어들어 깊이감이 느껴지는 효과가 있습니다. 결국 전체 스택이 그룹으로서 사라집니다.

데모: 카드 스태킹.

✨ 직접 사용해 보기

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

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