[CSS-09] 비디오 & 애니메이션

Comely·2025년 6월 6일

CSS

목록 보기
9/12

🎬 HTML 비디오 태그

기본 비디오 삽입

<video>
  <source src="video/sample.mp4" type="video/mp4">
  <source src="video/sample.webm" type="video/webm">
  <source src="video/sample.ogg" type="video/ogg">
  브라우저가 비디오를 지원하지 않습니다.
</video>

멀티 포맷 지원: 여러 형식을 제공하면 브라우저가 최적화된 포맷을 자동 선택

비디오 속성

<video 
  autoplay 
  muted 
  loop 
  controls
  poster="thumbnail.jpg" 
  preload="metadata"
  width="800" 
  height="450"
>
  <source src="video.mp4" type="video/mp4">
</video>
속성설명참고사항
autoplay자동 재생muted와 함께 사용해야 작동
muted음소거 상태자동재생 정책상 필수
loop반복 재생배경 비디오에 유용
controls재생 컨트롤 표시사용자 제어 가능
poster썸네일 이미지비디오 로드 전 표시
preload사전 로딩 설정auto, metadata, none

Preload 옵션

<!-- 전체 비디오 미리 다운로드 -->
<video preload="auto">
  <source src="video.mp4">
</video>

<!-- 메타데이터만 미리 로드 (권장) -->
<video preload="metadata">
  <source src="video.mp4">
</video>

<!-- 사용자가 재생할 때까지 로드하지 않음 -->
<video preload="none">
  <source src="video.mp4">
</video>

📺 배경 비디오 구현

HTML 구조

<div class="video-box">
  <video class="video-container" autoplay muted loop>
    <source src="video/background.mp4" type="video/mp4">
    <source src="video/background.webm" type="video/webm">
  </video>
  <div class="video-content">
    <h1>Welcome to Our Site</h1>
    <p>Amazing content over video background</p>
    <button class="cta-button">Get Started</button>
  </div>
</div>

CSS 스타일링

.video-box {
  position: relative;
  height: 100vh;
  width: 100%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.video-container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  min-width: 100%;
  min-height: 100%;
  width: auto;
  height: auto;
  z-index: -1;
  background-size: cover;
}

.video-content {
  position: relative;
  z-index: 1;
  text-align: center;
  color: white;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}

.video-content h1 {
  font-size: 3rem;
  margin-bottom: 1rem;
}

.video-content p {
  font-size: 1.2rem;
  margin-bottom: 2rem;
}

.cta-button {
  padding: 15px 30px;
  font-size: 1.1rem;
  background: rgba(255, 255, 255, 0.2);
  color: white;
  border: 2px solid white;
  border-radius: 5px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.cta-button:hover {
  background: white;
  color: #333;
}

반응형 배경 비디오

@media (max-width: 768px) {
  .video-container {
    /* 모바일에서는 이미지로 대체 */
    display: none;
  }
  
  .video-box {
    background-image: url('video-poster.jpg');
    background-size: cover;
    background-position: center;
  }
  
  .video-content h1 {
    font-size: 2rem;
  }
}

🎨 Transform 속성

기본 Transform 속성들

.transform-demo {
  /* 회전 */
  transform: rotate(45deg);
  
  /* 이동 */
  transform: translate(50px, 100px);
  transform: translateX(50px);
  transform: translateY(100px);
  
  /* 크기 조절 */
  transform: scale(1.5);
  transform: scaleX(2);
  transform: scaleY(0.5);
  
  /* 비틀기 */
  transform: skew(15deg, 5deg);
  transform: skewX(15deg);
  transform: skewY(5deg);
  
  /* 여러 속성 조합 */
  transform: rotate(45deg) scale(1.2) translateX(20px);
}

Transform의 장점

/* 나쁜 예: 레이아웃 재계산 발생 */
.bad-animation {
  transition: margin-left 0.3s;
}
.bad-animation:hover {
  margin-left: 100px; /* 레이아웃 재계산 */
}

/* 좋은 예: GPU 가속 사용 */
.good-animation {
  transition: transform 0.3s;
}
.good-animation:hover {
  transform: translateX(100px); /* 효율적 */
}

🎬 Keyframes 애니메이션

기본 문법

/* 1. 키프레임 정의 */
@keyframes slideIn {
  0% {
    transform: translateX(-100px);
    opacity: 0;
  }
  50% {
    transform: translateX(20px);
    opacity: 0.8;
  }
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 2. 애니메이션 적용 */
.slide-element {
  animation: slideIn 0.8s ease-out;
}

Animation 속성 상세

.complex-animation {
  animation-name: myAnimation;           /* 키프레임 이름 */
  animation-duration: 2s;                /* 지속 시간 */
  animation-timing-function: ease-in-out; /* 타이밍 함수 */
  animation-delay: 0.5s;                 /* 시작 지연 */
  animation-iteration-count: 3;          /* 반복 횟수 */
  animation-direction: alternate;        /* 방향 */
  animation-fill-mode: forwards;         /* 종료 후 상태 */
  animation-play-state: running;         /* 재생/일시정지 */
  
  /* 축약형 */
  animation: myAnimation 2s ease-in-out 0.5s 3 alternate forwards;
}

Animation Fill Mode

/* 애니메이션 종료 후 원래 상태로 복귀 (기본값) */
.animation-none {
  animation-fill-mode: none;
}

/* 애니메이션 종료 후 마지막 상태 유지 */
.animation-forwards {
  animation-fill-mode: forwards;
}

/* 애니메이션 시작 전 첫 번째 상태 적용 */
.animation-backwards {
  animation-fill-mode: backwards;
}

/* 시작 전과 종료 후 모두 적용 */
.animation-both {
  animation-fill-mode: both;
}

🚀 실전 애니메이션 예제

1. 흔들리는 버튼

.shake-button {
  padding: 15px 30px;
  font-size: 18px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: transform 0.3s ease;
}

.shake-button:hover {
  animation: shake 0.6s ease-in-out;
}

@keyframes shake {
  0%, 100% { 
    transform: rotate(0deg); 
  }
  25% { 
    transform: rotate(-5deg); 
  }
  50% { 
    transform: rotate(5deg); 
  }
  75% { 
    transform: rotate(-5deg); 
  }
}

2. 회전하는 플러스 버튼

.plus-button {
  font-size: 48px;
  color: #333;
  cursor: pointer;
  display: inline-block;
  transition: transform 0.3s ease;
}

.plus-button:hover {
  animation: rotatePlus 0.8s ease-out forwards;
}

@keyframes rotatePlus {
  0% { 
    transform: rotate(0deg) scale(1); 
  }
  25% { 
    transform: rotate(-15deg) scale(1.1); 
  }
  100% { 
    transform: rotate(45deg) scale(1.3); 
  }
}

3. 슬라이딩 메뉴

<nav class="sliding-menu">
  <h4>Menu</h4>
  <p class="menu-item">Home</p>
  <p class="menu-item">About</p>
  <p class="menu-item">Contact</p>
</nav>
.sliding-menu {
  position: fixed;
  left: 0;
  top: 0;
  width: 250px;
  height: 100vh;
  background: #333;
  color: white;
  padding: 30px 20px;
  transform: translateX(-200px);
  transition: all 0.5s ease;
  z-index: 1000;
}

.sliding-menu:hover {
  transform: translateX(0);
}

.sliding-menu h4 {
  text-align: right;
  transition: text-align 0.5s ease;
}

.sliding-menu:hover h4 {
  text-align: center;
}

.menu-item {
  cursor: pointer;
  padding: 10px 0;
  transition: all 0.3s ease;
}

.sliding-menu:hover .menu-item {
  animation: slideText 0.8s ease-out;
}

@keyframes slideText {
  0% { 
    transform: translateX(-100px); 
    opacity: 0;
  }
  50% { 
    transform: translateX(30px) skewX(-20deg); 
    opacity: 0.7;
  }
  100% { 
    transform: translateX(0) skewX(0deg); 
    opacity: 1;
  }
}

4. 페이드 인 카드 애니메이션

.card {
  background: white;
  border-radius: 10px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  padding: 20px;
  margin: 20px;
  opacity: 0;
  transform: translateY(50px);
  animation: fadeInUp 0.6s ease-out forwards;
}

.card:nth-child(2) { animation-delay: 0.2s; }
.card:nth-child(3) { animation-delay: 0.4s; }
.card:nth-child(4) { animation-delay: 0.6s; }

@keyframes fadeInUp {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

5. 로딩 스피너

.loader {
  width: 50px;
  height: 50px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #007bff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

6. 펄스 효과

.pulse-button {
  position: relative;
  padding: 15px 30px;
  background: #ff6b6b;
  color: white;
  border: none;
  border-radius: 50px;
  cursor: pointer;
}

.pulse-button::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: 50px;
  background: #ff6b6b;
  animation: pulse 2s infinite;
  z-index: -1;
}

@keyframes pulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  100% {
    transform: scale(1.3);
    opacity: 0;
  }
}

⚡ 성능 최적화

Will-Change 속성

/* 애니메이션 성능 향상 */
.animated-element {
  will-change: transform;
}

/* 애니메이션 완료 후 제거 */
.animated-element.animation-complete {
  will-change: auto;
}

GPU 가속 활용

.gpu-accelerated {
  /* 3D 변환으로 GPU 가속 활성화 */
  transform: translate3d(0, 0, 0);
  
  /* 또는 */
  transform: translateZ(0);
  
  /* 더 명시적인 방법 */
  will-change: transform;
  transform: translate3d(0, 0, 0);
}

효율적인 애니메이션 속성

/* 권장: 레이아웃에 영향 없는 속성들 */
.efficient-animation {
  transition: transform 0.3s, opacity 0.3s;
}

/* 비권장: 레이아웃 재계산 발생 */
.inefficient-animation {
  transition: width 0.3s, height 0.3s, margin 0.3s;
}

🎯 반응형 애니메이션

미디어 쿼리와 애니메이션

/* 데스크톱 애니메이션 */
@media (min-width: 768px) {
  .desktop-animation {
    animation: complexAnimation 2s ease-in-out;
  }
}

/* 모바일에서는 단순한 애니메이션 */
@media (max-width: 767px) {
  .desktop-animation {
    animation: simpleAnimation 1s ease-out;
  }
}

/* 사용자가 애니메이션을 원하지 않는 경우 */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

💡 실무 팁

애니메이션 디버깅

/* 개발 중 애니메이션 슬로우 모션 */
* {
  animation-duration: 10s !important;
}

/* 특정 요소만 슬로우 모션 */
.debug-animation {
  animation-duration: 5s !important;
}

재사용 가능한 애니메이션 클래스

/* 유틸리티 애니메이션 클래스 */
.fade-in {
  animation: fadeIn 0.5s ease-out forwards;
}

.slide-up {
  animation: slideUp 0.6s ease-out forwards;
}

.bounce-in {
  animation: bounceIn 0.8s ease-out forwards;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes slideUp {
  from { 
    transform: translateY(30px); 
    opacity: 0; 
  }
  to { 
    transform: translateY(0); 
    opacity: 1; 
  }
}

@keyframes bounceIn {
  0% { 
    transform: scale(0.3); 
    opacity: 0; 
  }
  50% { 
    transform: scale(1.05); 
    opacity: 0.8; 
  }
  70% { 
    transform: scale(0.9); 
    opacity: 0.9; 
  }
  100% { 
    transform: scale(1); 
    opacity: 1; 
  }
}

HTML 비디오 삽입부터 고급 CSS 애니메이션까지 정리해보았습니다.

profile
App, Web Developer

0개의 댓글