Skip to Content
WebCSSCSS 기본기18. 애니메이션: @keyframes로 등장 연출하기

이번 편의 결과물: index.html을 열면 히어로 제목·부제·버튼 2개가 위에서 아래 순서로 살짝 떠오르며 나타납니다. 다루는 개념: @keyframes 정의, animation 속성군(지속시간·반복·재생 상태), transition과의 차이(트리거 유무)

이 편에서 만드는 파일

web-practice/portfolio/ └── css/ └── styles.css ~ (@keyframes hero-enter 신규, .hero 자식 요소에 animation 추가)

17편까지 .hero는 배경·여백·글자 크기만 정리된 정적인 상태입니다. 이 편은 페이지가 열리는 순간 한 번만 실행되는 애니메이션을 추가합니다.

개념 정리

@keyframes는 애니메이션의 중간 단계를 이름 붙여 정의하는 규칙입니다. from/to(또는 0%/100%)로 시작과 끝을, 필요하면 그 사이 퍼센트로 중간 단계를 지정합니다.

@keyframes hero-enter { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }

정의한 @keyframesanimation 속성으로 요소에 연결합니다.

하위 속성역할이 사이트에서 쓰는 값
animation-name사용할 @keyframes 이름hero-enter
animation-duration한 번 재생에 걸리는 시간600ms
animation-timing-function속도 곡선ease-out
animation-delay재생 시작을 늦추는 시간요소마다 0ms400ms
animation-fill-mode재생 전·후 상태 유지 방식both(끝난 뒤 마지막 프레임 유지)

transition과 animation의 차이는 트리거입니다. transition:hover처럼 속성 값이 바뀌는 사건이 있어야 동작하고, 시작·끝 두 상태만 표현합니다. animation@keyframes로 여러 단계를 정의할 수 있고, 트리거 없이 요소가 화면에 나타나는 순간(또는 클래스가 붙는 순간) 스스로 재생을 시작합니다. 히어로 등장 연출처럼 “페이지가 열리자마자 자동으로” 실행돼야 하는 효과는 animation이 맞는 선택입니다.

흔한 오해는 animation-fill-mode를 생략하는 것입니다. 기본값(none)에서는 애니메이션이 끝나는 순간 요소가 @keyframes에 정의되지 않은 원래 스타일로 돌아가 버려, opacity: 0으로 시작한 요소가 재생 후 다시 안 보이는 것처럼 깜빡일 수 있습니다.

실습

1. 파일 열기

web-practice/portfolio/css/styles.css를 엽니다. .hero 규칙 아래에 이어서 씁니다.

2. @keyframes 정의

/* web-practice/portfolio/css/styles.css */ /* ...기존 리셋·토큰·레이아웃·헤더·버튼·카드 규칙 유지... */ @keyframes hero-enter { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }

3. 히어로 자식 요소에 순서대로 적용

index.html의 히어로 영역은 h1p → 버튼(기본) → 버튼(보조) 순서로 되어 있습니다. :nth-child로 순서를 골라 지연 시간을 다르게 줍니다.

.hero > * { animation: hero-enter 600ms ease-out both; } .hero > *:nth-child(2) { animation-delay: 150ms; } .hero > *:nth-child(3) { animation-delay: 300ms; } .hero > *:nth-child(4) { animation-delay: 400ms; }

첫 번째 규칙이 네 요소 모두에게 같은 @keyframes와 지속시간을 주고, 이후 세 규칙은 지연 시간만 덮어써 시작 시점을 어긋나게 만듭니다. 이렇게 하면 요소가 동시에 뜨지 않고 위에서부터 순서대로 나타납니다.

4. 사용자 접근성 설정 존중

일부 사용자는 운영체제에서 “동작 줄이기”를 켜 둡니다. 이 설정을 존중하는 규칙을 추가합니다.

@media (prefers-reduced-motion: reduce) { .hero > * { animation: none; } }

5. 실행

파일을 저장하고 index.html을 새로고침합니다. 캐시 때문에 애니메이션이 안 보이면 강력 새로고침(Ctrl + Shift + R)을 합니다.

6. 확인

  • 페이지를 열면 히어로 제목이 먼저, 부제가 그다음, 버튼 두 개가 순서대로 아래에서 살짝 떠오르며 나타납니다.
  • 전체 연출은 1초 안팎으로 끝나고, 끝난 뒤에는 요소들이 제자리에 고정되어 다시 사라지지 않습니다.
  • 개발자 도구에서 운영체제의 “동작 줄이기”(macOS: 손쉬운 사용 > 디스플레이, Windows: 접근성 설정)를 켜고 새로고침하면 애니메이션 없이 바로 나타납니다.
  • projects.html·contact.html은 히어로 영역이 없으므로 이 애니메이션의 영향을 받지 않습니다.

직접 해보기

  1. animation-delay 값을 모두 0ms로 바꿔 네 요소가 동시에 나타나는 것과 순서대로 나타나는 것의 느낌 차이를 비교해 보세요.
  2. @keyframes hero-enter50% 단계를 추가해 중간에 살짝 더 위로 올라갔다가 제자리로 내려오는 3단계 애니메이션을 만들어 보세요.

정답 확인

  1. 동시에 나타나면 “화면이 한 번에 켜지는” 느낌이고, 순서대로면 “요소가 하나씩 소개되는” 느낌입니다. 시안은 후자를 의도합니다.
  2. 예시:
@keyframes hero-enter { 0% { opacity: 0; transform: translateY(12px); } 60% { opacity: 1; transform: translateY(-2px); } 100% { opacity: 1; transform: translateY(0); } }

자주 하는 실수

증상원인고치는 법
애니메이션이 끝난 뒤 요소가 안 보인다animation-fill-mode를 생략해 재생 후 원래(opacity: 0) 스타일로 돌아갔다animation-fill-mode: both 또는 단축 속성에 both 포함
새로고침해도 애니메이션이 매번 안 보인다브라우저 캐시가 이전 CSS를 그대로 쓰고 있다강력 새로고침 또는 개발자 도구를 열어 두고 캐시 비활성화 옵션 사용
모든 요소가 동시에 나타난다animation-delay를 개별 요소에 다르게 주지 않았다:nth-child로 요소를 구분해 지연 시간을 다르게 지정
동작 줄이기 설정을 켜도 계속 움직인다prefers-reduced-motion 미디어 쿼리를 추가하지 않았다@media (prefers-reduced-motion: reduce)에서 animation: none 지정

확인 문제

문제 14지선다
transition과 비교했을 때 animation(@keyframes)의 특징으로 옳은 것은?
문제 24지선다
animation-fill-mode: both를 생략하면 생길 수 있는 문제는?
문제 34지선다
prefers-reduced-motion: reduce 미디어 쿼리를 추가하는 이유는?
문제 44지선다
:nth-child(2)로 두 번째 자식 요소만 골라 animation-delay를 다르게 주는 이유는?

참고 자료

Last updated on