CSS
CSS Animation & Transition 완벽 가이드 2026
CSS transition과 animation의 차이, 사용법, 성능 최적화까지. 부드러운 UI 인터랙션을 만드는 실전 가이드.
Toolypet Team
Development Team
CSS Animation & Transition 완벽 가이드 2026
버튼 호버 효과, 로딩 스피너, 페이지 전환... 모던 웹에서 애니메이션은 필수입니다.
CSS만으로 JavaScript 없이 부드러운 인터랙션을 만드는 방법을 알아봅니다.
Transition vs Animation
| 특성 | Transition | Animation |
|---|---|---|
| 트리거 | 상태 변화 필요 (:hover 등) | 자동 실행 가능 |
| 키프레임 | 시작-끝 2개 | 무제한 |
| 반복 | 불가 | 무한 반복 가능 |
| 방향 | 순방향만 | 역방향, 교대 가능 |
| 사용 | 간단한 상태 전환 | 복잡한 애니메이션 |
CSS Transition
기본 문법
transition: property duration timing-function delay;
| 속성 | 설명 | 기본값 |
|---|---|---|
property | 전환할 속성 | all |
duration | 지속 시간 | 0s |
timing-function | 가속 곡선 | ease |
delay | 시작 지연 | 0s |
기본 예제
/* 단일 속성 */
.button {
background: #3b82f6;
transition: background 0.3s ease;
}
.button:hover {
background: #2563eb;
}
/* 다중 속성 */
.card {
transform: translateY(0);
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(0,0,0,0.2);
}
Timing Functions
/* 내장 함수 */
.ease { transition-timing-function: ease; } /* 기본 */
.linear { transition-timing-function: linear; } /* 일정 속도 */
.ease-in { transition-timing-function: ease-in; } /* 느리게 시작 */
.ease-out { transition-timing-function: ease-out; } /* 느리게 끝 */
.ease-in-out { transition-timing-function: ease-in-out; }
/* 커스텀 베지어 곡선 */
.custom { transition-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55); }
/* 단계적 */
.steps { transition-timing-function: steps(4, end); }
인기 베지어 곡선
/* 바운스 */
.bounce { transition: all 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55); }
/* 스무스 */
.smooth { transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); }
/* 스냅 */
.snap { transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); }
CSS Animation
기본 문법
@keyframes 애니메이션이름 {
from { /* 시작 상태 */ }
to { /* 끝 상태 */ }
}
/* 또는 */
@keyframes 애니메이션이름 {
0% { /* 시작 */ }
50% { /* 중간 */ }
100% { /* 끝 */ }
}
.element {
animation: 이름 duration timing-function delay iteration-count direction fill-mode;
}
Animation 속성
| 속성 | 값 | 설명 |
|---|---|---|
animation-name | 키프레임 이름 | 필수 |
animation-duration | 시간 | 필수 |
animation-timing-function | 타이밍 | ease |
animation-delay | 지연 시간 | 0s |
animation-iteration-count | 반복 횟수 | 1, infinite |
animation-direction | 방향 | normal, reverse, alternate |
animation-fill-mode | 종료 상태 | none, forwards, backwards, both |
animation-play-state | 재생 상태 | running, paused |
실전 애니메이션 예제
1. 페이드 인
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 0.5s ease forwards;
}
/* 위에서 페이드 인 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in-down {
animation: fadeInDown 0.5s ease forwards;
}
2. 로딩 스피너
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e5e7eb;
border-top-color: #3b82f6;
border-radius: 50%;
animation: spin 1s linear infinite;
}
3. 펄스 효과
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.pulse {
animation: pulse 2s ease-in-out infinite;
}
/* 펄스 링 */
@keyframes pulseRing {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(2);
opacity: 0;
}
}
.pulse-ring {
position: relative;
}
.pulse-ring::before {
content: '';
position: absolute;
inset: 0;
border: 2px solid #3b82f6;
border-radius: 50%;
animation: pulseRing 1.5s ease-out infinite;
}
4. 바운스
@keyframes bounce {
0%, 100% {
transform: translateY(0);
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
}
50% {
transform: translateY(-25%);
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
}
.bounce {
animation: bounce 1s infinite;
}
5. 쉐이크 (에러)
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
20%, 40%, 60%, 80% { transform: translateX(5px); }
}
.shake {
animation: shake 0.5s ease;
}
/* JavaScript로 트리거 */
/* element.classList.add('shake'); */
6. 타이핑 효과
@keyframes typing {
from { width: 0; }
to { width: 100%; }
}
@keyframes blink {
50% { border-color: transparent; }
}
.typing {
overflow: hidden;
white-space: nowrap;
border-right: 3px solid;
width: 0;
animation:
typing 3s steps(30) forwards,
blink 0.7s step-end infinite;
}
7. 스켈레톤 로딩
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
.skeleton {
background: linear-gradient(
90deg,
#f0f0f0 25%,
#e0e0e0 50%,
#f0f0f0 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
Transform과 함께 사용
Transform 속성
/* 이동 */
transform: translateX(100px);
transform: translateY(50px);
transform: translate(100px, 50px);
/* 회전 */
transform: rotate(45deg);
transform: rotateX(45deg); /* 3D */
transform: rotateY(45deg); /* 3D */
/* 크기 */
transform: scale(1.5);
transform: scaleX(2);
/* 기울기 */
transform: skew(10deg);
/* 조합 */
transform: translateX(100px) rotate(45deg) scale(1.2);
3D 효과
/* 부모에 원근감 설정 */
.perspective-container {
perspective: 1000px;
}
/* 카드 플립 */
.card-3d {
transform-style: preserve-3d;
transition: transform 0.6s;
}
.card-3d:hover {
transform: rotateY(180deg);
}
.card-front, .card-back {
backface-visibility: hidden;
}
.card-back {
transform: rotateY(180deg);
}
성능 최적화
GPU 가속 속성
/* ✅ GPU 가속 (성능 좋음) */
transform: translateX(100px);
transform: scale(1.1);
transform: rotate(45deg);
opacity: 0.5;
/* ❌ CPU 연산 (리플로우 발생) */
left: 100px;
width: 200px;
height: 200px;
margin: 10px;
will-change
/* 애니메이션 대상에 힌트 */
.animated {
will-change: transform, opacity;
}
/* 호버 시에만 */
.card:hover {
will-change: transform;
}
/* 애니메이션 후 제거 권장 */
리플로우 피하기
/* ❌ 피해야 할 패턴 */
.bad {
animation: move 1s infinite;
}
@keyframes move {
to { left: 100px; } /* 리플로우 발생 */
}
/* ✅ 권장 패턴 */
.good {
animation: moveGood 1s infinite;
}
@keyframes moveGood {
to { transform: translateX(100px); } /* GPU 가속 */
}
접근성
모션 감소 설정 존중
/* 사용자가 모션 감소를 원할 때 */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* 또는 선택적으로 */
@media (prefers-reduced-motion: reduce) {
.animated {
animation: none;
}
.transition {
transition: none;
}
}
실전 UI 패턴
버튼 호버
.button {
background: #3b82f6;
color: white;
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
}
.button:hover {
background: #2563eb;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(59,130,246,0.4);
}
.button:active {
transform: translateY(0);
}
메뉴 드롭다운
.dropdown {
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: all 0.2s ease;
}
.menu:hover .dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
모달 열기
.modal-overlay {
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease;
}
.modal-overlay.active {
opacity: 1;
visibility: visible;
}
.modal {
transform: scale(0.9) translateY(20px);
transition: transform 0.3s ease;
}
.modal-overlay.active .modal {
transform: scale(1) translateY(0);
}
순차 등장
.item {
opacity: 0;
transform: translateY(20px);
animation: fadeInUp 0.5s ease forwards;
}
.item:nth-child(1) { animation-delay: 0.1s; }
.item:nth-child(2) { animation-delay: 0.2s; }
.item:nth-child(3) { animation-delay: 0.3s; }
@keyframes fadeInUp {
to {
opacity: 1;
transform: translateY(0);
}
}
FAQ
Q1: transition이 작동하지 않아요
A: 확인할 것:
- 변경되는 속성이 애니메이션 가능한지
display: none에서 전환 시 작동 안 함- 시작 값과 끝 값이 명시되어 있는지
Q2: animation이 끝난 후 상태를 유지하려면?
A: animation-fill-mode: forwards 사용
.element {
animation: fadeIn 1s ease forwards;
}
Q3: 성능이 나빠요
A:
transform과opacity만 애니메이션will-change적절히 사용- 너무 많은 요소에 애니메이션 피하기
Q4: JavaScript와 CSS 애니메이션 중 뭐가 좋아요?
A:
- 간단한 전환: CSS
- 복잡한 시퀀스: JavaScript (GSAP 등)
- 사용자 입력 반응: JavaScript
- 자동 루프: CSS
마무리
CSS 애니메이션 핵심:
- Transition: 상태 변화에 반응
- Animation: 자동 실행, 키프레임
- Transform: GPU 가속, 성능 우수
- 타이밍: ease, cubic-bezier
- 접근성: prefers-reduced-motion 존중
관련 도구
| 도구 | 용도 |
|---|---|
| Animation 생성기 | 키프레임 생성 |
| Transform 생성기 | 변환 효과 |
| 필터 생성기 | CSS 필터 |
CSSanimationtransition애니메이션UI인터랙션
저자 소개
Toolypet Team
Development Team
The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.
Web DevelopmentCSS ToolsDeveloper ToolsSEOSecurity