CSS 독학 가이드 7 - 애니메이션과 전환 효과
애니메이션이 UX를 바꾼다
정적인 웹사이트와 움직이는 웹사이트의 차이를 아시나요? 버튼을 클릭했을 때 바로 변하는 것보다 부드럽게 전환되는 게 훨씬 자연스럽고 고급스러워 보여요.
저는 처음 CSS 애니메이션을 배웠을 때 “와, 이거 JavaScript 없이도 되네!” 하고 놀랐어요. 생각보다 훨씬 간단하거든요.
Transition (전환 효과)
A 상태에서 B 상태로 부드럽게 변하게 만들어요.
기본 문법
.button {
background: blue;
transition: background 0.3s;
}
.button:hover {
background: red;
}
실행 결과:
마우스를 올리면 배경색이 부드럽게 변합니다
마우스를 올리면 파랑에서 빨강으로 0.3초 동안 부드럽게 바뀝니다!
속성 상세
.box {
transition-property: background; /* 전환할 속성 */
transition-duration: 0.3s; /* 지속 시간 */
transition-timing-function: ease; /* 속도 곡선 */
transition-delay: 0.1s; /* 딜레이 */
}
/* 축약형 */
.box {
transition: background 0.3s ease 0.1s;
/* 속성 시간 곡선 딜레이 */
}
여러 속성 동시 전환
.button {
transition:
background 0.3s ease,
transform 0.3s ease,
box-shadow 0.3s ease;
}
.button:hover {
background: #007bff;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
모든 속성 전환
.box {
transition: all 0.3s ease;
}
주의: 성능 이슈가 있을 수 있어요. 가능하면 구체적인 속성 지정을 추천!
Timing Functions (속도 곡선)
애니메이션의 속도 변화를 제어해요.
/* 기본 제공 */
transition-timing-function: linear; /* 일정한 속도 */
transition-timing-function: ease; /* 느리게-빠르게-느리게 (기본) */
transition-timing-function: ease-in; /* 느리게 시작 */
transition-timing-function: ease-out; /* 느리게 끝 */
transition-timing-function: ease-in-out; /* 느리게 시작하고 끝 */
실전 추천:
- 대부분:
ease또는ease-out - 드롭다운 등장:
ease-out - 드롭다운 사라짐:
ease-in
Cubic-bezier (커스텀 곡선)
.bounce {
transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
cubic-bezier.com에서 직접 만들어보세요!
Transform (변형)
요소를 이동, 회전, 크기 변경, 기울이기 등을 할 수 있어요.
translate (이동)
.box {
transform: translateX(100px); /* 오른쪽으로 100px */
transform: translateY(-50px); /* 위로 50px */
transform: translate(100px, -50px); /* X, Y 동시 */
}
왜 margin 대신 transform을?
- transform은 GPU 가속 사용 (더 부드러움)
- 레이아웃에 영향 안 줌
- 애니메이션 성능 좋음
scale (크기 조절)
.box {
transform: scale(1.5); /* 1.5배 확대 */
transform: scale(0.8); /* 0.8배 축소 */
transform: scale(2, 0.5); /* 가로 2배, 세로 0.5배 */
}
rotate (회전)
.box {
transform: rotate(45deg); /* 45도 회전 */
transform: rotate(-90deg); /* -90도 회전 */
}
여러 변형 동시 적용
.box {
transform: translate(50px, 100px) rotate(45deg) scale(1.2);
}
순서 주의! 왼쪽부터 적용돼요.
실전 예제 1: 호버 효과
버튼 들어올리기
.button {
background: #007bff;
color: white;
padding: 12px 24px;
border: none;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.button:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(0,123,255,0.4);
}
.button:active {
transform: translateY(0);
}
실행 결과:
버튼이 들어올려지며 그림자가 생깁니다
카드 확대
.card {
transition: transform 0.3s ease;
}
.card:hover {
transform: scale(1.05);
}
이미지 줌인
.image-container {
overflow: hidden;
}
.image-container img {
transition: transform 0.5s ease;
}
.image-container:hover img {
transform: scale(1.2);
}
실전 예제 2: 로딩 스피너
<div class="spinner"></div>
.spinner {
width: 50px;
height: 50px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
실행 결과:
로딩 스피너가 계속 회전합니다
Animation (@keyframes)
복잡한 애니메이션을 만들 때 사용해요. transition보다 강력!
기본 문법
@keyframes slide-in {
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.box {
animation: slide-in 1s ease;
}
여러 단계 애니메이션
@keyframes bounce {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-30px);
}
100% {
transform: translateY(0);
}
}
.ball {
animation: bounce 1s ease infinite;
}
실행 결과:
공이 위아래로 튀어오릅니다
Animation 속성 상세
.box {
animation-name: slide-in; /* 애니메이션 이름 */
animation-duration: 1s; /* 지속 시간 */
animation-timing-function: ease; /* 속도 곡선 */
animation-delay: 0.5s; /* 딜레이 */
animation-iteration-count: infinite; /* 반복 횟수 */
animation-direction: alternate; /* 방향 */
animation-fill-mode: forwards; /* 끝난 후 상태 */
}
/* 축약형 */
.box {
animation: slide-in 1s ease 0.5s infinite alternate forwards;
}
iteration-count 옵션:
1: 한 번만 (기본)3: 3번 반복infinite: 무한 반복
direction 옵션:
normal: 정방향 (기본)reverse: 역방향alternate: 정방향 → 역방향 번갈아alternate-reverse: 역방향 → 정방향 번갈아
fill-mode 옵션:
none: 끝나면 원래대로 (기본)forwards: 끝난 상태 유지backwards: 시작 전에 첫 프레임 적용both: forwards + backwards
실전 예제 3: 페이드 인
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.content {
animation: fade-in 0.8s 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; }
실전 예제 4: 펄스 효과
@keyframes pulse {
0%, 100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.1);
opacity: 0.7;
}
}
.notification-badge {
animation: pulse 2s ease-in-out infinite;
}
실전 예제 5: 타이핑 효과
@keyframes typing {
from { width: 0; }
to { width: 100%; }
}
@keyframes blink {
50% { border-color: transparent; }
}
.typing {
width: 0;
overflow: hidden;
border-right: 2px solid;
white-space: nowrap;
animation:
typing 3s steps(30) forwards,
blink 0.5s step-end infinite;
}
성능 최적화
GPU 가속 속성만 애니메이션
✅ 좋은 성능:
transform(translate, scale, rotate)opacity
❌ 나쁜 성능:
width,heightmargin,paddingtop,left,right,bottom
/* ❌ 나쁜 예 */
.box {
transition: width 0.3s;
}
.box:hover {
width: 300px;
}
/* ✅ 좋은 예 */
.box {
transition: transform 0.3s;
}
.box:hover {
transform: scaleX(1.5);
}
will-change 힌트
.box {
will-change: transform, opacity;
}
브라우저에게 “이거 애니메이션할 거야”라고 미리 알려줘요. 성능 향상!
주의: 모든 요소에 쓰면 오히려 성능 저하. 실제 애니메이션하는 요소에만!
JavaScript와 연동
애니메이션 끝 감지
const box = document.querySelector('.box');
box.addEventListener('animationend', () => {
console.log('애니메이션 끝!');
});
box.addEventListener('transitionend', () => {
console.log('전환 끝!');
});
클래스 토글로 애니메이션
.modal {
opacity: 0;
transform: scale(0.8);
transition: all 0.3s ease;
}
.modal.active {
opacity: 1;
transform: scale(1);
}
const modal = document.querySelector('.modal');
modal.classList.add('active'); // 애니메이션 시작
자주 쓰는 애니메이션 라이브러리
직접 만들기 귀찮으면:
- Animate.css: 즉시 사용 가능한 애니메이션
- GSAP: 복잡한 애니메이션
- Framer Motion: React 전용
- AOS: 스크롤 애니메이션
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<h1 class="animate__animated animate__bounceIn">Hello!</h1>
접근성 고려사항
움직임에 민감한 사용자를 위해:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
사용자가 시스템에서 “애니메이션 줄이기”를 설정하면 애니메이션이 거의 사라져요.
다음 단계
애니메이션을 마스터했으니 이제 고급 선택자와 가상 요소를 배울 차례예요. 더 정교한 스타일링과 특수 효과를 만들 수 있습니다!
다음 글에서는 자식 선택자, 가상 클래스, ::before/::after 등을 다룰 거예요.
실습 과제:
- 버튼에 호버 효과 추가하기
- 로딩 스피너 만들어보기
- 카드가 페이드인하며 나타나는 효과 만들기
- 자신만의 keyframes 애니메이션 만들어보기
애니메이션은 과하면 오히려 방해가 돼요. 적절한 타이밍과 속도로 자연스럽게!
시리즈 네비게이션
- 이전글: CSS 독학 가이드 - 반응형 디자인
- 현재글: CSS 독학 가이드 - 애니메이션과 전환 효과
- 다음글: CSS 독학 가이드 - 고급 선택자와 가상 요소