Taeyoung Kim

Engineering

CSS Animation 가이드

CSS Animation 가이드 학습 내용을 정리한 백필 노트입니다.

이 글은 2025년 학습 기록을 블로그 형식으로 정리한 백필 노트입니다.


1. CSS Animation 개요

CSS Animation은 자바스크립트 없이 요소의 크기, 색상, 모양 등을 제어하여 동적 효과를 부여하는 기술입니다. CSS 전환(Transition)이 시작과 종료 상태만 제어하는 반면, **애니메이션(Animation)**은 시작, 중간, 종료 등 여러 단계의 상태를 정의할 수 있어 더 복잡하고 다채로운 효과를 구현할 수 있습니다.


2. @keyframes 규칙

@keyframes는 애니메이션의 각 단계를 정의하는 CSS 규칙입니다. 애니메이션의 시작과 끝을 fromto로 정의하거나, 0%부터 100%까지의 백분율로 여러 중간 단계를 정의할 수 있습니다.

CSS

/* from-to 방식 */
@keyframes 애니메이션이름 {
  from { /* 시작 스타일 */ }
  to { /* 종료 스타일 */ }
}

/* percentage 방식 */
@keyframes 애니메이션이름 {
  0% { /* 시작 스타일 */ }
  50% { /* 중간 스타일 */ }
  100% { /* 종료 스타일 */ }
}

3. animation 속성

animation은 개별 애니메이션 속성들을 한 번에 지정할 수 있는 단축 속성입니다.

  • 문법: animation: 이름 지속시간 [타이밍함수] [대기시간] [반복횟수] [반복방향] [전후상태] [재생/정지] [조합방식];
  • 필수값: animation-name, animation-duration

| 속성 | 의미 | 기본값 | | --- | --- | --- | | animation-name | 적용할 @keyframes의 이름 | none | | animation-duration | 애니메이션 지속 시간 | 0s | | animation-delay | 애니메이션 대기 시간 | 0s | | animation-timing-function | 가속도 등 타이밍 함수 지정 | ease | | animation-iteration-count | 반복 횟수 | 1 | | animation-direction | 반복 방향 | normal | | animation-fill-mode | 애니메이션 전후 상태 | none | | animation-play-state | 재생과 정지 상태 | running | | animation-composition | 기본 스타일과의 조합 방식 | replace |


4. 개별 animation 속성 상세

animation-name

적용할 @keyframes 규칙의 이름을 지정합니다.

animation-duration

애니메이션이 한 번 재생되는 데 걸리는 시간을 지정합니다.

animation-delay

애니메이션이 시작되기 전까지의 대기 시간을 설정합니다. 음수 값을 사용하면 애니메이션이 해당 시간만큼 미리 시작된 것처럼 보입니다.

animation-timing-function

애니메이션의 진행 속도를 제어하는 타이밍(이징) 함수를 지정합니다.

| 값 | 의미 | | --- | --- | | linear | 일정하게 | | ease | 빠르게 시작하여 느려짐 (기본값) | | ease-in | 느리게 시작하여 빨라짐 | | ease-out | 빠르게 시작하여 느려짐 | | ease-in-out | 느리게-빠르게-느리게 | | cubic-bezier(n,n,n,n) | 베지어 곡선을 이용해 직접 값을 정의 | | steps(n, [점프타이밍]) | 애니메이션을 n단계로 분할하여 재생 |

  • cubic-bezier(): 4개의 수치를 이용해 정교한 가속도 곡선을 만들 수 있습니다.
  • steps(): 애니메이션을 부드럽게 전환하는 대신 지정된 단계 수만큼 뚝뚝 끊어서 보여줍니다. '점프 타이밍' 값(jump-start, jump-end 등)으로 각 단계의 시작/종료 시점을 조절할 수 있습니다.

animation-iteration-count

애니메이션의 반복 횟수를 지정합니다. infinite로 설정하면 무한 반복됩니다.

animation-direction

애니메이션의 반복 방향을 지정합니다.

| 값 | 의미 | | --- | --- | | normal | 정방향으로만 반복 (기본값) | | reverse | 역방향으로만 반복 | | alternate | 정방향과 역방향을 번갈아 가며 왕복 | | alternate-reverse | 역방향과 정방향을 번갈아 가며 왕복 |

animation-fill-mode

애니메이션이 시작되기 전(대기 시간 중)과 끝난 후의 요소 스타일을 지정합니다.

| 값 | 의미 | | --- | --- | | none | 애니메이션 전후에 원래 스타일로 돌아감 (기본값) | | forwards | 애니메이션 종료 후, 마지막 프레임의 스타일을 유지 | | backwards | 대기 시간 동안, 첫 프레임의 스타일을 적용 | | both | forwardsbackwards를 모두 적용 |

animation-play-state

애니메이션의 재생 상태를 제어합니다.

| 값 | 의미 | | --- | --- | | running | 애니메이션을 재생 (기본값) | | paused | 애니메이션을 일시 정지 |

animation-composition (최신 속성)

기존 transform과 같은 기본 스타일이 있을 때, 애니메이션 스타일과 어떻게 조합할지 지정합니다.

| 값 | 의미 | | --- | --- | | replace | 기본 스타일을 애니메이션 스타일로 대체 (기본값) | | add | 기본 스타일에 애니메이션 스타일을 더함 | | accumulate | 기본 스타일과 애니메이션 스타일을 섞음(누적) |


5. 애니메이션 예제

Simple Spinner (로딩 스피너)

HTML

<style>
.hloader {
  --hloader-color: #e96900;
  --hloader-size: 80px;
  --hloader-weight: 8px;
  --hloader-duration: 1s;
  width: var(--hloader-size);
  height: var(--hloader-size);
  color: var(--hloader-color);
  border: var(--hloader-weight) solid;
  border-top-color: transparent;
  border-radius: 50%;
  box-sizing: border-box;
  animation: hloader var(--hloader-duration) infinite linear;
}
@keyframes hloader {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style>
<div class="hloader"></div>

SVG Spinner (고급 스피너)

HTML

<style>
.hloader {
  --hloader-color: #e96900;
  --hloader-size: 100px;
  --hloader-weight: 4;
  --hloader-duration: 1.5s;
  width: var(--hloader-size);
  height: var(--hloader-size);
  color: var(--hloader-color);
}
.hloader svg {
  animation: hloader-svg var(--hloader-duration) linear infinite;
}
.hloader circle {
  animation: hloader-circle var(--hloader-duration) linear infinite;
  fill: transparent;
  stroke-width: var(--hloader-weight);
  stroke-dasharray: 80, 200;
  stroke-dashoffset: 0px;
  stroke: currentColor;
}
@keyframes hloader-svg {
  100% { transform: rotate(1turn); }
}
@keyframes hloader-circle { 
  0% { stroke-dasharray: 1, 200; stroke-dashoffset: 0px; } 
  50% { stroke-dasharray: 100, 200; stroke-dashoffset: -15px; } 
  100% { stroke-dasharray: 100, 200; stroke-dashoffset: -124px; }
}
</style>
<div class="hloader">
  <svg viewBox="22.857 22.857 45.714 45.714">
    <circle cx="45.714" cy="45.714" r="20"></circle>
  </svg>
</div>

Skeleton Loader (스켈레톤 로더)

HTML

<style>
.hskeleton {
  background-color: #222;
  border-radius: 4px;
  position: relative;
  overflow: hidden;
}
.hskeleton::after {
  content: "";
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background-image: linear-gradient(270deg, 
    rgba(255,255,255,0), 
    rgba(255,255,255,.1), 
    rgba(255,255,255,0)
  );
  transform: translateX(-100%);
  animation: hskeleton-loader 2s infinite;
}
@keyframes hskeleton-loader {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}
</style>
<div class="hskeleton" style="width: 200px; height: 100px;"></div>