Skip to Content
WebCSS모던 CSS16. 스크롤 연동 애니메이션으로 카드 등장시키기

이번 편의 결과물: projects.html을 스크롤하면 카드가 순서대로 나타난다. 지원하지 않는 브라우저에서는 처음부터 모든 카드가 그대로 보인다 · 다루는 개념: animation-timelineview() 함수, 타임라인 축과 animation-range, 제한적 지원 상황에서의 @supports 폴백

이 편에서 만드는 파일

portfolio/ └── css/ └── styles.css ~ 카드 등장 애니메이션과 폴백 추가

개념 정리

animation-timeline은 애니메이션의 진행 기준을 시간이 아니라 스크롤 위치로 바꾸는 속성입니다. 사용자가 스크롤할 때마다 애니메이션이 그만큼 진행되고, 스크롤을 멈추면 애니메이션도 그 자리에 멈춥니다.

scroll()과 view()의 차이

함수기준용도
scroll()스크롤 컨테이너 전체의 스크롤 진행률(0퍼센트–100퍼센트)페이지 상단 진행바 등
view()그 요소가 뷰포트(또는 지정한 컨테이너)에 들어오고 나가는 구간요소별 등장·퇴장 연출

카드가 화면에 들어올 때 나타나는 효과에는 view()가 맞습니다.

animation-range로 구간 지정

view()만으로는 요소가 뷰포트에 걸쳐 있는 전체 구간(들어오기 시작 ~ 완전히 나가기)을 타임라인으로 씁니다. 등장 효과만 원하면 animation-range로 “들어오는 구간”만 좁힙니다.

키워드의미
entry 0%요소가 뷰포트에 처음 닿는 지점
entry 100%요소가 뷰포트에 완전히 들어온 지점
cover 0%부터 100%까지요소가 뷰포트를 지나가는 전체 구간
exit 0%부터 100%까지요소가 뷰포트를 빠져나가는 구간
animation-range: entry 0% cover 30%;

요소가 뷰포트에 닿기 시작해서(entry 0%) 전체 구간의 30%만큼 지나갈 때까지(cover 30%) 애니메이션을 끝내겠다는 뜻입니다. 카드가 완전히 화면 가운데 오기 전에 등장 효과가 끝나도록 좁힌 값입니다.

지원 상황과 폴백 전략

2026-09 기준 animation-timeline: view()는 Chrome·Edge·Safari 26 이상에서 동작하지만 Firefox는 아직 플래그 뒤에 있어 Baseline에 도달하지 못했습니다(Interop 2026 과제). 이 실습은 지원 브라우저에서만 애니메이션을 걸고, 미지원 브라우저에서는 처음부터 카드가 다 보이게 만듭니다.

기본 원칙: 카드는 기본 상태로 opacity: 1(항상 보임)로 두고, @supports (animation-timeline: view())를 만족하는 브라우저에서만 초기 상태를 opacity: 0으로 낮춘 뒤 애니메이션으로 다시 1로 올립니다. 이렇게 하면 미지원 브라우저는 애니메이션도 못 보고 카드가 안 보이는 최악의 상황도 피할 수 있습니다.

실습

1. 등장 애니메이션 키프레임 작성

/* portfolio/css/styles.css (@layer components 안) */ @keyframes card-reveal { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } }

2. 지원 브라우저에서만 초기 숨김 + 스크롤 연동 적용

/* portfolio/css/styles.css (@layer components 안) */ .project-card { opacity: 1; /* 기본값: 항상 보임(폴백) */ } @supports (animation-timeline: view()) { .project-card { opacity: 0; animation: card-reveal linear both; animation-timeline: view(); animation-range: entry 0% cover 30%; } }

@supports 블록 안에서만 opacity: 0으로 낮추므로, 이 속성을 모르는 브라우저는 블록 전체를 무시하고 기본값인 opacity: 1을 그대로 씁니다.

3. 모션 선호 대응 추가

/* portfolio/css/styles.css */ @media (prefers-reduced-motion: reduce) { .project-card { animation: none !important; opacity: 1; } }

prefers-reduced-motion: reduce인 사용자에게는 스크롤 연동 애니메이션도 꺼서 항상 카드가 바로 보이게 합니다.

4. 실행

npx serve portfolio

projects.html을 열고 페이지 아래로 천천히 스크롤합니다.

5. 확인

확인 1. 지원 브라우저(Chrome·Edge 최신)에서 스크롤하면 카드가 아래에서 위로 살짝 이동하며 나타난다 확인 2. 스크롤을 멈추면 애니메이션도 그 진행 지점에서 멈춘다(시간이 아니라 스크롤 위치가 기준) 확인 3. 개발자 도구에서 CSS.supports("animation-timeline", "view()")를 콘솔에 입력해 지원 여부 확인 확인 4. 미지원 브라우저(또는 Firefox)에서는 스크롤 없이도 카드가 처음부터 전부 보인다 확인 5. 운영체제 설정에서 "동작 줄이기"를 켜면 지원 브라우저에서도 애니메이션 없이 카드가 바로 보인다

직접 해보기

  1. animation-rangeentry 0% cover 30%에서 entry 0% cover 60%로 늘려 등장 속도가 어떻게 느려지는지 비교해 봅니다.
  2. 카드마다 등장 순서가 살짝 어긋나 보이도록 nth-childanimation-delay처럼 보이는 효과를 animation-range 시작점을 다르게 줘서 만들어 봅니다(시간 기반이 아니므로 animation-delay는 스크롤 타임라인에 그대로 쓸 수 없습니다).

정답 보기

/* portfolio/css/styles.css */ .project-card:nth-child(2) { animation-range: entry 5% cover 35%; } .project-card:nth-child(3) { animation-range: entry 10% cover 40%; }

스크롤 타임라인에서는 animation-delay가 시간 단위라 스크롤 진행과 맞물리지 않습니다. 대신 각 카드의 animation-range 시작 지점을 조금씩 밀어서 순차 등장 느낌을 냅니다.

자주 하는 실수

증상원인고치는 법
Firefox에서 카드가 계속 안 보임@supports 밖에서 opacity: 0을 기본값으로 지정기본값은 opacity: 1로 두고 @supports 안에서만 0으로 낮춤
스크롤해도 애니메이션이 전혀 안 걸림animation-timeline: view()만 있고 animation 속성에 키프레임 이름을 안 넣음animation: card-reveal linear both;animation-timeline을 함께 지정
카드가 화면 한가운데를 넘도록 계속 움직임animation-range를 지정하지 않아 전체 cover 구간을 다 씀animation-range: entry 0% cover 30%처럼 구간을 좁힘
동작 줄이기 설정을 켜도 애니메이션이 남아 있음prefers-reduced-motion 미디어 쿼리를 추가하지 않음@media (prefers-reduced-motion: reduce)에서 animation: none 처리

확인 문제

문제 14지선다
스크롤 연동 애니메이션에서 view() 함수가 기준으로 삼는 것은?
문제 24지선다
animation-range: entry 0% cover 30%의 의미는?
문제 34지선다
이 실습에서 카드의 기본 opacity를 1로 두고 @supports 블록 안에서만 0으로 낮춘 이유는?
문제 44지선다
2026-09 기준 animation-timeline: view()의 Baseline 상태와 이 실습이 취한 조치로 옳은 것은?

참고 자료

Last updated on