✨ CSS 애니메이션 & 트랜지션

CSS 애니메이션
완전 정복

자바스크립트 없이 CSS만으로 만드는 hover 효과, 페이드인, 스피너, 바운스 애니메이션. transition@keyframes 두 가지만 알면 사이트가 살아납니다.

🎨 Pure CSS ⚡ JS 불필요 🖱️ 클릭해서 체험 📋 복사 가능한 코드
① Concept

transition vs @keyframes

CSS 애니메이션에는 두 가지 접근법이 있어요. 상태 변화에는 transition, 반복 움직임에는 @keyframes를 사용합니다.

💡

언제 뭘 쓸까요? hover·focus처럼 "A 상태 → B 상태"로 부드럽게 바뀌는 효과라면 transition이 간단해요. 스피너, 바운스처럼 여러 단계로 반복되는 효과라면 @keyframes를 사용하세요.

🔀

transition

CSS 속성 값이 바뀔 때 그 변화를 부드럽게 만들어줘요. hover, focus, class 추가 등 상태 변화에 씁니다. 단 두 상태(시작→끝)만 정의해요.

🔄

@keyframes

0%부터 100%까지 여러 키프레임을 직접 정의해요. 자동 반복, 방향 전환, 일시정지 등 세밀한 제어가 가능합니다. 로딩 스피너, 주의 효과에 적합해요.

🔧

transform

요소를 이동(translate), 회전(rotate), 확대(scale), 기울이기(skew)해요. GPU가 처리하므로 성능이 가장 좋습니다. 애니메이션의 단짝이에요.

will-change

브라우저에게 "이 요소는 곧 애니메이션될 거야"라고 미리 알려줘요. 무거운 애니메이션을 부드럽게 처리하는 성능 힌트지만, 남용하면 오히려 역효과예요.

속성트리거반복중간 단계사용 사례
transition 상태 변화 (hover 등) 없음 2단계만 hover 효과, 메뉴 슬라이드
@keyframes 자동 / JS 클래스 추가 가능 무제한 스피너, 바운스, 페이드인
② Types

알아야 할 핵심 속성 4가지

이 네 가지만 조합하면 사이트에서 보이는 애니메이션 99%를 만들 수 있어요.

⏱️

duration — 재생 시간

transition: all 0.3s → 0.3초 동안 변화해요. 일반적으로 hover는 0.15s~0.3s, 페이드인은 0.4s~0.8s가 자연스러워요. 너무 길면 답답하고 너무 짧으면 인지 못해요.

📈

easing — 가속도 곡선

ease는 느리게 시작해 빠르게 가다 느리게 끝나요(가장 자연스러움). ease-in은 가속, ease-out은 감속, linear는 일정 속도예요. 스피너엔 linear, 버튼엔 ease를 주로 써요.

🔁

iteration — 반복 횟수

animation-iteration-count: infinite로 무한 반복해요. 숫자를 넣으면 그 횟수만 반복돼요. animation-direction: alternate를 함께 쓰면 앞뒤로 왕복합니다.

⏸️

fill-mode — 시작/끝 상태

animation-fill-mode: both는 애니메이션 전후 상태를 유지해요. forwards는 끝 상태를 유지, backwards는 시작 상태를 유지해요. 페이드인처럼 한 번만 실행될 때 꼭 필요해요.

③ Code

복사해서 바로 쓰는 코드

가장 자주 쓰이는 패턴 4가지예요. 복사해서 AI에게 "이 스타일로 우리 사이트에 적용해줘"라고 하면 바로 쓸 수 있어요.

1 — 버튼 hover 트랜지션

클릭 가능한 느낌을 주는 가장 기본적인 패턴이에요.

style.css
/* 버튼 hover 효과 */
.btn {
  background: #4f46e5;
  color: #fff;
  padding: 12px 24px;
  border-radius: 8px;
  border: none;
  cursor: pointer;
  transition: background .2s, transform .15s, box-shadow .2s;
}
.btn:hover {
  background: #4338ca;
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(79,70,229,.35);
}
.btn:active {
  transform: translateY(0);
}

2 — 요소 페이드인 (등장 애니메이션)

페이지 로드 시 또는 스크롤할 때 자연스럽게 나타나는 효과예요.

style.css
/* 아래에서 위로 페이드인 */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.fade-in-up {
  animation: fadeInUp 0.6s ease both;
}

/* 딜레이로 순서 연출 */
.card:nth-child(1) { animation-delay: 0s; }
.card:nth-child(2) { animation-delay: .1s; }
.card:nth-child(3) { animation-delay: .2s; }

3 — 로딩 스피너

API 요청 중 보여줄 수 있는 간단한 CSS 스피너예요.

style.css
/* 로딩 스피너 */
@keyframes spin {
  to { transform: rotate(360deg); }
}

.spinner {
  width: 40px;
  height: 40px;
  border: 3px solid #e5e7eb;
  border-top-color: #4f46e5;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

4 — 주의 유도 (pulse) 효과

CTA 버튼이나 알림 배지에 주의를 끄는 효과예요.

style.css
/* 주의 유도 pulse */
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(79,70,229,.4); }
  70%       { box-shadow: 0 0 0 12px rgba(79,70,229,0); }
}

.pulse {
  animation: pulse 2s ease-out infinite;
  border-radius: 50%; /* 또는 버튼 border-radius */
}
💡

성능 팁: 애니메이션을 만들 때는 opacitytransform만 변경하세요. width, height, margin, top을 변경하면 레이아웃을 다시 계산해야 해서 버벅임이 생겨요. GPU가 처리하는 transformopacity가 성능이 가장 좋습니다.

④ Demo

클릭해서 직접 체험해보세요

각 카드의 버튼을 클릭하면 CSS 애니메이션이 실행됩니다. 코드는 ③ 섹션에서 복사할 수 있어요.

🔄

spin — 회전

rotate(360deg) 무한 반복

🏀

bounce — 바운스

translateY로 위아래 반복

💛

pulse — 확대·축소

scale(1.2) 반복

shake — 흔들기

translateX로 좌우 흔들

fadeInUp — 등장

투명도 + 위로 이동

🎷

swing — 흔들리기

rotate 왕복 반복

transition 플레이그라운드

버튼을 클릭해서 transform의 다양한 효과를 확인하세요.

transform 선택
🎯
⑤ Prompt Tip

AI 프롬프트 팁

AI에게 애니메이션을 요청할 때 "예쁘게 해줘"보다 구체적으로 어떤 동작을 원하는지 설명할수록 정확한 코드를 받을 수 있어요.

✦ 바이브코더 프롬프트

아래 프롬프트를 복사해서 Claude, ChatGPT, Cursor에 붙여넣어 보세요.

내 웹페이지 버튼과 카드에 CSS 애니메이션을 추가해줘.

요구사항:
- .btn 클래스: hover 시 2px 위로 올라가고 그림자가 생기는 transition
- .card 클래스: 페이지 로드 시 아래에서 위로 페이드인, 카드마다 0.1s씩 딜레이
- .loading 클래스: 회전하는 스피너 (CSS만으로)
- .badge-new 클래스: pulse 효과로 시선 유도

조건:
- JavaScript 없이 CSS만으로 구현
- 성능을 위해 transform, opacity만 변경
- 기존 HTML은 그대로 유지하고 CSS만 추가
⑥ FAQ

자주 묻는 질문

CSS 애니메이션을 처음 배울 때 헷갈리는 부분들이에요.

상태가 두 가지(기본/hover)라면 transition이 훨씬 간단해요. 세 단계 이상이거나 자동으로 반복되어야 하는 효과라면 @keyframes + animation을 사용하세요. 대부분의 hover 버튼, 메뉴 슬라이드는 transition으로 충분합니다.
width, height, top, margin 같은 레이아웃 속성을 애니메이션하면 브라우저가 레이아웃을 매 프레임 재계산해서 버벅여요. transformopacity만 변경하면 GPU가 처리하므로 훨씬 부드럽습니다. 위치 이동은 left 대신 translateX를 사용하세요.
애니메이션 시작 전에는 0% 상태를, 끝난 후에는 100% 상태를 유지해요. 페이드인처럼 "opacity:0에서 시작해 끝난 뒤에도 opacity:1로 유지"할 때 꼭 필요합니다. both를 생략하면 애니메이션이 끝나자마자 초기 상태로 돌아가요.
요소에 클래스를 추가하고 제거하는 방식을 사용해요. element.classList.add('animated')로 클래스를 붙이고, 애니메이션이 끝나면 classList.remove로 제거하면 다음 클릭 때 다시 실행됩니다. animationend 이벤트로 끝나는 시점을 잡을 수 있어요.
transition@keyframes는 모든 모던 브라우저(Chrome, Firefox, Safari, Edge)에서 지원돼요. 구형 iOS Safari 대응이 필요하면 -webkit- 접두어를 붙이지만, 2020년 이후 버전이라면 대부분 불필요합니다.