CSS 애니메이션과 트랜지션
3장까지 우리는 HTML로 웹 페이지의 구조를 잡고, CSS로 스타일과 레이아웃을 꾸미는 방법을 익혔습니다. 이제 여러분의 웹 페이지에 생명을 불어넣을 차례입니다. 단순히 정적인 정보를 보여주는 것을 넘어, 요소들이 부드럽게 움직이고 변화하며 사용자에게 시각적인 피드백을 제공한다면, 웹 페이지는 훨씬 더 매력적이고 사용자 친화적으로 변할 것입니다.
이번 장에서는 CSS만으로 웹 요소에 동적인 움직임을 부여하는 두 가지 강력한 기법인 CSS 트랜지션(Transition) 과 CSS 애니메이션(Animation) 에 대해 학습합니다. 트랜지션은 속성값이 변할 때 부드러운 전환 효과를, 애니메이션은 여러 단계의 복잡한 움직임을 제어할 수 있게 해줍니다. 이들을 통해 웹 페이지의 사용자 경험(UX)을 크게 향상시키고, 시각적인 즐거움을 더할 수 있습니다.
CSS 트랜지션 (Transition)
트랜지션은 CSS 속성값이 변할 때, 그 변화가 즉시 일어나는 대신 지정된 시간 동안 점진적으로(부드럽게) 일어나도록 하는 기능입니다. 주로 사용자의 마우스 오버(:hover
), 클릭(:active
), 포커스(:focus
) 등 특정 이벤트에 반응하여 요소의 상태가 변할 때 유용하게 사용됩니다.
트랜지션 관련 주요 속성
트랜지션을 적용하려면 주로 다음 네 가지 속성을 사용합니다.
-
transition-property
: 트랜지션 효과를 적용할 CSS 속성을 지정합니다.all
(기본값): 모든 CSS 속성에 트랜지션 적용width
,height
,background-color
,transform
,opacity
등 특정 속성 지정- 여러 속성 지정 시 쉼표(
,
)로 구분
.box { transition-property: width; /* 너비 변화에만 트랜지션 적용 */ transition-property: background-color, transform; /* 배경색과 변형에 트랜지션 적용 */ transition-property: all; /* 모든 속성 변화에 트랜지션 적용 */ }
-
transition-duration
: 트랜지션이 완료되는 데 걸리는 시간을 지정합니다.s
(초) 또는ms
(밀리초) 단위를 사용합니다.- 0초는 기본값으로, 트랜지션 없이 즉시 변화합니다.
.box { transition-duration: 0.5s; /* 0.5초 동안 변화 */ transition-duration: 500ms; /* 500밀리초 동안 변화 (0.5초와 동일) */ }
-
transition-timing-function
: 트랜지션 속도의 변화 패턴을 지정합니다. (가속도 곡선)ease
(기본값): 느리게 시작 → 빠르게 → 느리게 끝남 (부드러운 효과)linear
: 일정한 속도ease-in
: 느리게 시작 → 점차 빨라짐ease-out
: 빠르게 시작 → 점차 느려짐ease-in-out
: 느리게 시작 → 빨라짐 → 느리게 끝남 (ease
와 유사하나 시작/끝이 더 극적)cubic-bezier(n, n, n, n)
: 자신만의 커스텀 가속도 곡선을 정의 (고급)steps(n, direction)
: n개의 단계로 뚝뚝 끊어지는 변화 (애니메이션에 유용)
.box { transition-timing-function: ease-in-out; /* 시작과 끝이 부드러운 변화 */ }
-
transition-delay
: 트랜지션이 시작되기 전까지 기다릴 시간을 지정합니다.s
(초) 또는ms
(밀리초) 단위를 사용합니다.
.box { transition-delay: 0.2s; /* 0.2초 후에 트랜지션 시작 */ }
transition
단축 속성
위 네 가지 속성을 한 줄에 요약하여 작성할 수 있습니다. 순서는 중요하지 않지만, 시간을 나타내는 값이 두 개일 경우 첫 번째는 duration
, 두 번째는 delay
로 인식됩니다.
.box {
/* property | duration | timing-function | delay */
transition: all 0.5s ease-in-out 0.1s;
/* 배경색 변화에 0.3초 ease 효과 */
transition: background-color 0.3s ease;
/* 너비 변화에 0.5초, 배경색 변화에 0.3초 */
transition: width 0.5s, background-color 0.3s;
}
트랜지션 활용 예시
간단한 버튼에 마우스 오버 효과를 적용해 봅시다.
<style>
.my-button {
background-color: #3498db;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
/* 트랜지션 적용 */
transition: background-color 0.3s ease-out, transform 0.3s ease-out;
}
.my-button:hover {
background-color: #2980b9; /* 배경색 변경 */
transform: translateY(-3px); /* 위로 살짝 이동 */
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); /* 그림자 추가 */
}
</style>
<button class="my-button">마우스를 올려보세요</button>
CSS 애니메이션 (Animation)
트랜지션이 '속성 변화에 대한 부드러운 전환'이라면, 애니메이션은 '여러 단계에 걸쳐 다양한 속성을 원하는 시간 동안 반복적으로 제어'할 수 있는 훨씬 강력한 기능입니다. @keyframes
규칙을 사용하여 애니메이션의 각 단계를 직접 정의합니다.
@keyframes
규칙 정의
애니메이션의 이름과 각 단계(프레임)에서의 CSS 스타일을 정의합니다. 각 단계는 퍼센트(%)로 지정하며, 0%
(또는 from
)은 시작 상태, 100%
(또는 to
)는 끝 상태를 의미합니다. 중간 단계를 여러 개 지정할 수 있습니다.
@keyframes slideIn {
0% { /* 시작 상태 */
transform: translateX(-100%); /* 왼쪽으로 완전히 벗어남 */
opacity: 0;
}
50% { /* 50% 지점 */
opacity: 0.5;
}
100% { /* 끝 상태 */
transform: translateX(0); /* 원래 위치로 돌아옴 */
opacity: 1;
}
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
애니메이션 관련 주요 속성
정의된 @keyframes
애니메이션을 HTML 요소에 적용하려면 다음 속성들을 사용합니다.
-
animation-name
: 적용할@keyframes
애니메이션의 이름을 지정합니다. (필수) -
animation-duration
: 한 번의 애니메이션 주기가 완료되는 데 걸리는 시간을 지정합니다. (s
또는ms
, 필수) -
animation-timing-function
: 애니메이션 속도의 변화 패턴을 지정합니다. (트랜지션과 동일) -
animation-delay
: 애니메이션이 시작되기 전까지 기다릴 시간을 지정합니다. -
animation-iteration-count
: 애니메이션이 반복될 횟수를 지정합니다.1
(기본값): 한 번만 재생infinite
: 무한 반복- 특정 숫자: 지정된 횟수만큼 반복
.element { animation-iteration-count: 3; /* 3번 반복 */ animation-iteration-count: infinite; /* 무한 반복 */ }
-
animation-direction
: 애니메이션의 재생 방향을 지정합니다.normal
(기본값): 0% → 100% 순으로 재생reverse
: 100% → 0% 순으로 재생alternate
: 순방향 → 역방향 → 순방향 반복 (짝수 번째는 역방향)alternate-reverse
: 역방향 → 순방향 → 역방향 반복
.element { animation-direction: alternate; /* 왔다 갔다 반복 */ }
-
animation-fill-mode
: 애니메이션이 끝난 후 또는 시작되기 전 요소의 스타일을 어떻게 유지할지 지정합니다.none
(기본값): 애니메이션 시작 전/후에 원래 스타일로 돌아감.forwards
: 애니메이션이 끝난 후 마지막@keyframes
상태를 유지.backwards
: 애니메이션 시작 전0%
(또는from
) 상태를 유지. (딜레이가 있을 경우)both
:forwards
와backwards
모두 적용.
.element { animation-fill-mode: forwards; /* 애니메이션 끝난 상태 유지 */ }
-
animation-play-state
: 애니메이션의 재생 상태를 제어합니다.running
(기본값): 재생 중paused
: 일시 정지
.element:hover { animation-play-state: paused; /* 마우스 오버 시 애니메이션 일시 정지 */ }
animation
단축 속성
위 모든 속성을 한 줄에 요약하여 작성할 수 있습니다. 순서가 중요하며, 필수 값인 animation-name
과 animation-duration
은 반드시 포함되어야 합니다.
.element {
/* name | duration | timing-function | delay | iteration-count | direction | fill-mode | play-state */
animation: slideIn 1s ease-out 0.5s infinite alternate forwards;
}
애니메이션 활용 예시
웹 페이지 로딩 시 나타나는 요소 또는 무한 반복되는 로딩 애니메이션을 만들어 봅시다.
<style>
/* 애니메이션 정의 */
@keyframes fadeInSlideUp {
0% {
opacity: 0;
transform: translateY(20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes rotate360 {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.fade-in-box {
width: 200px;
height: 100px;
background-color: #2ecc71; /* 에메랄드 */
color: white;
display: flex;
justify-content: center;
align-items: center;
margin: 50px auto;
border-radius: 8px;
font-size: 1.2em;
/* 애니메이션 적용 */
animation-name: fadeInSlideUp;
animation-duration: 0.8s;
animation-timing-function: ease-out;
animation-fill-mode: backwards; /* 애니메이션 시작 전 0% 상태 유지 (투명, 아래로) */
animation-delay: 0.5s; /* 0.5초 후에 시작 */
}
.spinner {
width: 50px;
height: 50px;
border: 5px solid #f3f3f3; /* 연한 회색 테두리 */
border-top: 5px solid #3498db; /* 파란색 상단 테두리 */
border-radius: 50%; /* 원형 */
margin: 30px auto;
/* 애니메이션 적용 */
animation: rotate360 1s linear infinite; /* 1초 동안 무한히 선형 회전 */
}
</style>
<div class="fade-in-box">나타나는 박스</div>
<div class="spinner"></div>
트랜지션 vs 애니메이션: 언제 무엇을 쓸까?
-
트랜지션
- 간단한 상태 변화: 버튼 호버 효과, 메뉴 확장/축소, 탭 전환 등 두 가지 상태(시작-끝) 간의 부드러운 전환에 적합합니다.
- 사용자 상호작용에 의해 트리거:
:hover
,:focus
,:active
, JavaScript로 클래스 추가/제거 등 이벤트에 의해 속성값이 변할 때 주로 사용합니다. - 코드가 비교적 간결합니다.
-
애니메이션
- 복잡한 다단계 움직임: 로딩 스피너, 슬라이드쇼, 특정 경로를 따라 움직이는 요소, 무한 반복되는 시각 효과 등 여러 프레임을 거치는 복잡한 움직임에 적합합니다.
- 자동으로 시작/반복: 페이지 로딩 시 자동으로 시작되거나, 무한 반복되는 효과에 주로 사용됩니다.
@keyframes
를 통해 각 프레임을 세밀하게 제어할 수 있습니다.
결론: 간단한 UI 인터랙션에는 트랜지션을, 복잡하거나 반복적인 시각 효과에는 애니메이션을 사용한다고 생각하면 됩니다.
실습: 웹 페이지에 동적인 효과 추가하기
배운 트랜지션과 애니메이션 속성들을 활용하여 실제 웹 페이지에 동적인 효과를 추가해 봅시다.
-
프로젝트 폴더 구조
dynamic_web.htmlmotion.css -
dynamic_web.html
파일 작성dynamic_web.html <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS 애니메이션과 트랜지션 실습</title> <link rel="stylesheet" href="css/motion.css"> </head> <body> <header> <h1 class="page-title">동적인 웹 페이지 만들기</h1> <p class="subtitle">CSS Transition과 Animation의 힘!</p> </header> <main> <section class="transition-section"> <h2>1. CSS 트랜지션 예시</h2> <div class="button-container"> <button class="hover-button">마우스 오버해보세요</button> <div class="box-grow">크기/색깔 변환 박스</div> </div> </section> <section class="animation-section"> <h2>2. CSS 애니메이션 예시</h2> <div class="loading-spinner"></div> <div class="bouncing-ball"></div> <div class="slide-in-text">짜잔! 등장하는 텍스트!</div> </section> </main> <footer> <p>© 2025 CSS Motion Practice. 모든 권리 보유.</p> </footer> </body> </html>
-
css/motion.css
파일 작성css/motion.css /* 기본 설정 */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f0f2f5; color: #333; line-height: 1.6; padding-bottom: 50px; } header { background-color: #34495e; color: white; text-align: center; padding: 30px 20px; box-shadow: 0 3px 6px rgba(0,0,0,0.2); margin-bottom: 30px; } .page-title { font-size: 2.8em; margin-bottom: 5px; } .subtitle { font-size: 1.2em; font-style: italic; } main { max-width: 900px; margin: 0 auto; padding: 0 20px; } section { background-color: white; padding: 30px; margin-bottom: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } section h2 { color: #2980b9; font-size: 2em; margin-bottom: 25px; text-align: center; } /* ------------------------------------------- */ /* 1. CSS 트랜지션 예시 */ /* ------------------------------------------- */ .button-container { display: flex; justify-content: center; align-items: center; gap: 40px; flex-wrap: wrap; padding: 20px; } .hover-button { background-color: #2ecc71; /* 에메랄드 */ color: white; padding: 15px 30px; border: none; border-radius: 8px; cursor: pointer; font-size: 1.1em; font-weight: bold; outline: none; /* 포커스 시 아웃라인 제거 */ /* 트랜지션 적용: 모든 변화에 0.3초 ease-out 효과 */ transition: all 0.3s ease-out; } .hover-button:hover { background-color: #27ae60; /* 진한 에메랄드 */ transform: scale(1.05) translateY(-5px); /* 확대 및 살짝 위로 이동 */ box-shadow: 0 8px 15px rgba(0, 0, 0, 0.2); /* 그림자 진하게 */ } .box-grow { width: 150px; height: 150px; background-color: #e74c3c; /* 벽돌색 */ color: white; display: flex; justify-content: center; align-items: center; border-radius: 15px; font-size: 1.1em; cursor: pointer; /* 트랜지션 적용: 너비, 높이, 배경색, border-radius에 0.4초 ease 효과 */ transition: width 0.4s ease, height 0.4s ease, background-color 0.4s ease, border-radius 0.4s ease; } .box-grow:hover { width: 200px; /* 너비 증가 */ height: 200px; /* 높이 증가 */ background-color: #c0392b; /* 배경색 변경 */ border-radius: 50%; /* 원형으로 변경 */ } /* ------------------------------------------- */ /* 2. CSS 애니메이션 예시 */ /* ------------------------------------------- */ /* 로딩 스피너 애니메이션 */ @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .loading-spinner { width: 60px; height: 60px; border: 6px solid #f3f3f3; /* 밝은 회색 테두리 */ border-top: 6px solid #3498db; /* 파란색 상단 테두리 */ border-radius: 50%; margin: 30px auto; /* 중앙 정렬 */ /* 애니메이션 적용 */ animation: spin 1.2s linear infinite; /* 1.2초 동안 선형 무한 회전 */ } /* 통통 튀는 공 애니메이션 */ @keyframes bounce { 0%, 100% { transform: translateY(0); } /* 시작과 끝은 제자리 */ 50% { transform: translateY(-50px); } /* 중간에 위로 50px */ } .bouncing-ball { width: 50px; height: 50px; background-color: #f1c40f; /* 노란색 */ border-radius: 50%; margin: 50px auto; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); /* 애니메이션 적용 */ animation: bounce 1.5s ease-in-out infinite alternate; /* 1.5초 동안 ease-in-out으로 무한히 왕복 */ } /* 슬라이드인 텍스트 애니메이션 */ @keyframes slideInFromLeft { 0% { transform: translateX(-100%); /* 왼쪽 밖에서 시작 */ opacity: 0; } 100% { transform: translateX(0); /* 원래 위치로 이동 */ opacity: 1; } } .slide-in-text { font-size: 2.5em; font-weight: bold; color: #27ae60; text-align: center; margin-top: 50px; opacity: 0; /* 초기에는 투명하게 */ /* 애니메이션 적용 */ animation: slideInFromLeft 1s ease-out forwards; /* 1초 동안 ease-out으로 재생 후 마지막 상태 유지 */ animation-delay: 0.5s; /* 0.5초 후에 애니메이션 시작 */ } /* 푸터 */ footer { background-color: #34495e; color: #ecf0f1; text-align: center; padding: 20px 0; margin-top: 50px; font-size: 0.9em; }
-
결과 확인
- Live Server를 통해
dynamic_web.html
파일을 열어보세요. - 트랜지션 섹션:
hover-button
에 마우스를 올렸다 내렸다 하며 배경색 변화와 크기/위치/그림자 변화가 부드럽게 일어나는 것을 확인하세요.box-grow
에 마우스를 올렸다 내렸다 하며 너비, 높이, 배경색, 테두리 반경(원형으로)이 부드럽게 전환되는 것을 확인하세요.
- 애니메이션 섹션:
- 페이지를 로드하자마자
loading-spinner
가 계속 회전하는 것을 확인하세요. bouncing-ball
이 통통 튀어 오르는 동작을 무한 반복하는 것을 확인하세요.- 페이지 로드 후 잠시 뒤(
animation-delay
)slide-in-text
가 왼쪽에서 부드럽게 나타나는 것을 확인하세요.
- 페이지를 로드하자마자
- Live Server를 통해
이번 장에서는 CSS만으로 웹 페이지에 동적인 효과를 부여하는 강력한 두 가지 기법인 CSS 트랜지션(Transition) 과 CSS 애니메이션(Animation) 을 학습했습니다.
- 트랜지션은 CSS 속성값이 변할 때 부드러운 전환 효과를 주는 데 사용되며, 주로 사용자 상호작용에 의해 트리거되는 간단한 상태 변화에 적합합니다.
transition-property
,transition-duration
,transition-timing-function
,transition-delay
속성들을 통해 전환 효과를 세밀하게 제어할 수 있습니다. - 애니메이션은
@keyframes
규칙을 통해 여러 단계의 복잡한 움직임을 정의하고,animation-name
,animation-duration
,animation-iteration-count
,animation-direction
,animation-fill-mode
등 다양한 속성으로 애니메이션의 재생 방식을 제어할 수 있습니다. 이는 로딩 효과나 반복적인 시각 효과 등 더 복잡한 움직임을 구현하는 데 적합합니다.
이 두 가지 기법을 적절히 활용함으로써 여러분의 웹 페이지는 단순한 정보 전달을 넘어 사용자에게 시각적인 즐거움과 더 나은 인터랙션을 제공하는 동적인 경험을 선사할 수 있게 될 것입니다.