0ju-log
💻 Frontend

[React] CSS 애니메이션의 모든 것

💡 시작하기

디프만에서 프로젝트를 하다가 인터랙션을 구현하게 되었는데요. 하지만 애니메이션에 대해 구현해본 적이 거의 없는 저에게는 큰 도전이었어요. 이것저것 찾아보며 공부한 내용들을 정리해보려고 해요!

🎨 animation

CSS 애니메이션을 구현하기 위해 animation 속성을 사용할 수 있어요.

속성설명예시
animation-delay애니메이션의 시작시간을 지정animation-delay: 5s
5초 뒤에 애니메이션 시작
animation-direction애니메이션이 종료되고 다시 처음부터
시작할지 역방향으로 진행할지 지정animation-direction: reverse
애니메이션이 역방향으로 진행됨
animation-duration한 싸이클의 애니메이션이
얼마에 걸쳐 일어날지 지정animation-duration: 5s
애니메이션이 5초 동안 진행됨
animation-iteration-count애니메이션이 몇 번 반복될지 지정.
infinite로 지정하여 무한히 반복 가능animation-iteration-count: 2
애니메이션 2번 반복
animation-name애니메이션의 중간 상태를 지정.
@keyframes와 함께 사용animation-name: slideIn
slideIn이라는 중간 상태 지정
animation-play-state애니메이션을 멈출지
다시 시작할지 결정animation-play-state: running
애니메이션 다시 시작
animation-timing-function중간 상태의 전환을
어떻게 할지 결정animation-timing-function: linear
애니메이션의 속도가 처음부터 끝까지 일정
animation-fill-mode애니메이션이 시작되기 전이나
끝나고 난 후 어떤 값이 적용될지 지정animation-fill-mode: forwards
애니메이션이 끝난 후 그 지점에 그대로 위치

animation의 속성들은 각각 작성할 수도 있지만, 여러 속성의 값들을 한 번에 작성할 수도 있어요.

ex) animation: scaleAnimation 5s infinite animation: {name} {duration} {iteration-count}

🔑 @keyframes

animation-name에서 사용하는 @keyframes가 있는데요.

애니메이션을 재생할 각 프레임의 스타일을 정의하는 것으로 from 속성이나 0% 속성에 설정한 스타일에서 출발해 to 속성이나 100% 속성에 설정한 스타일로 점차 바뀌면서 애니메이션이 재생돼요.

시작 지점과 끝 지점의 중간에 %를 통해 특정 시점의 상태도 지정할 수 있어요.

@keyframes scaleAnimation {
  0% {
    transform: translate(-50%, -50%) scale(0);
    opacity: 100;
  }
  100% {
    transform: translate(-50%, -50%) scale(2);
    opacity: 0;
  }
}
.firstWave {
  animation: scaleAnimation 5s infinite;
}

실제 제가 작성한 코드를 예시로 가지고 왔어요.

@keyframes으로 만든 애니메이션에 네이밍(scaleAnimation)을 해주고 0%(시작 지점)의 상태와 100%(끝 지점)의 상태를 지정해주었어요.

🤔 transform, translate, transition

애니메이션에서 항상 제가 헷갈렸던 부분이 transform, translate, transition 이에요. 단어들이 너무 비슷하기도 해서 이왕 애니메이션에 정리한 김에 제대로 알아보고 싶었어요!

transform

📖 transform : 요소에 회전, 크기 조절, 기울이기, 이동 효과를 부여할 수 있는 CSS 속성

CSS transform 속성 정리 (표)

속성설명예시
rotate(angle)2D 평면에서 요소를 회전transform: rotate(0.5turn);
(180도 회전)
rotateX(angle)X축 기준으로 회전transform: rotateX(10deg);
(X축 기준 10도 회전)
rotateY(angle)Y축 기준으로 회전transform: rotateY(10deg);
(Y축 기준 10도 회전)
translate(x, y)X, Y축으로 요소 이동transform: translate(12px, 50%);
(X축 12px, Y축 50% 이동)
translateX(n)X축 방향으로 이동transform: translateX(2em);
(X축 2em 이동)
translateY(n)Y축 방향으로 이동transform: translateY(2px);
(Y축 2px 이동)
scale(x, y)X, Y축 방향으로 크기 조절transform: scale(2, 0.5);
(X축 2배, Y축 0.5배)
scaleX(n)X축 크기 조절transform: scaleX(2);
(X축 2배)
scaleY(n)Y축 크기 조절transform: scaleY(0.5);
(Y축 0.5배)
skew(x-angle, y-angle)X, Y축 기준으로 요소 기울이기transform: skew(30deg, 20deg);
(X축 30도, Y축 20도 기울이기)
skewX(angle)X축 기준으로 요소 기울이기transform: skewX(30deg);
(X축 30도 기울이기)
skewY(angle)Y축 기준으로 요소 기울이기transform: skewY(1.07rad);
(Y축 1.07 라디안 기울이기)

translate

📖 translate : 요소를 화면의 특정 방향으로 이동시키는 CSS transform 속성

원래 위치를 기준으로 상대적으로 이동하며, position, margin, top/right/bottom/left 없이도 부드럽고 깔끔하게 위치를 조정할 수 있어요.

  • transform: translate(x, y) ex) transform: translate(50%, 100px)

transition

📖 transition : 요소의 상태 변화를 부드럽게 하는 애니메이션 속성

원래 위치를 기준으로 상대적으로 이동하며, position, margin, top/right/bottom/left 없이도 부드럽고 깔끔하게 위치를 조정할 수 있어요.

속성설명예시
transition-property애니메이션 적용 대상transition-property: background-color, transform;
transition-duration애니메이션 지속 시간transition-duration: 0.5s;
transition-timing-function애니메이션 속도 조절transition-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
transition-delay애니메이션 시작 전 지연 시간transition-delay: 2s;
  • transitionanimation과 마찬가지로 다중 속성을 적용할 수 있어요
    • transition: [property] [duration] [timing-function] [delay]; ex) transition: all 0.5s ease-in-out 2s;

animation vs transition

해당 내용들을 찾아보다가 animation과 transition이 단일 속성이나 사용법 등 거의 같다는 것을 알게 되었는데요. 둘이 무슨 차이점이 있길래 따로 쓰이는 건지 궁금해서 정리해봤어요.

속성사용 목적주요 특징
transition상태 변화 시 부드럽게 이동사용자가 트리거 (hover, 클릭 등)
animation독립적인 애니메이션자동 실행 가능, 반복(loop) 가능

animation은 렌더링이 시작하자마자 시작되는 애니메이션의 속성들을 정의한 것이라면 transition은 어떠한 이벤트(hover, focus, …)가 발생했을 때 시작되는 애니메이션의 속성들을 정의한 거라고 볼 수 있어요.

한 줄 요약

  • transform : 요소를 변형하는 CSS 속성
  • translate : transform의 하위 기능으로, 요소를 X, Y, Z축 방향으로 이동
  • transition : 요소의 속성이 변할 때 애니메이션의 효과를 부드럽게 적용함
.box {
  transform: translateX(0);
  transition: transform 0.3s ease-in-out;
}

.box:hover {
  transform: translateX(50px);
}

종합해서 애니메이션을 만들어보아요

@keyframes scaleAnimation {
    0% {
      transform: translate(-50%, -50%) scale(0);
    }
    100% {
      transform: translate(-50%, -50%) scale(2);
      opacity: 0;
    }
  }

이 코드는 아까 위에서도 봤듯이 프로젝트에서 사용하는 애니메이션이에요. 원이 안에서 바깥으로 퍼지면서 점점 없어지는 파동 애니메이션을 구현하고 싶었어요.

그래서 @keyframes를 통해 위와 같이 시작 시점의 위치(translate)와 크기(scale), 끝 시점의 위치(translate)와 크기(scale)를 작성해서 점점 커지는 애니메이션을 만들 수 있도록 구현했어요.

또한 opacity 속성을 사용하여 점점 페이드 아웃이 되는 것처럼 보이도록 했어요.

.firstWave {
    animation: scaleAnimation 4s infinite linear;
  }
  .secondWave {
    animation: scaleAnimation 4s infinite linear;
    animation-delay: 0.15s;
  }

다음으로 animation을 사용하여 중간 속성을 정의해주는 name에 @keyframes를 통해 만든 애니메이션의 이름을 넣어주고, 이 애니메이션을 4초 동안 지속할 수 있도록 duration을 설정했어요.

애니메이션을 반복할 수 있도록 iteration-count 에는 infinite를 넣어주었으며, 애니메이션의 전환은 timing-functionlinear를 넣어 애니메이션의 속도가 모두 일정하도록 설정했어요.

또한 secondWave는 firstWave가 적용된 것보다 더 늦게 시작하여 파동이 추가적으로 생기는 것처럼 보여야 해요, 따라서 animation delay를 0.15s를 적용하였어요.

위와 같은 결과물이 완성되었어요 ☺️

📄 참고