CSS3 트랜지션과 2D 변환을 활용한 고성능 UI 애니메이션 구현

CSS3 트랜지션(Transition)의 기본 개념과 문법

CSS3의 트랜지션은 요소의 상태 변화가 발생할 때, 급격한 시각적 변화를 완화하여 자연스러운 중간 단계를 제공하는 기능입니다. 트랜지션이 적용되지 않으면 너비, 색상, 위치 등의 속성 변경이 즉시 발생하지만, 트랜지션을 사용하면 변화의 과정이 시각적으로 표현되어 사용자 경험(UX)을 크게 향상시킬 수 있습니다.

트랜지션의 기본 문법은 다음과 같습니다.

transition: <속성> <지속 시간> <타이밍 함수> <지연 시간>
  • 속성: 너비, 높이, transform 등 변화를 줄 CSS 속성. 여러 개일 경우 쉼표로 구분하거나 all을 사용.
  • 지속 시간: 변화가 완료되는 데 걸리는 시간(초 또는 밀리초).
  • 타이밍 함수: 변화의 속도 곡선. 기본값은 ease이며, linear(등속), ease-in(가속), ease-out(감속), ease-in-out(가속 후 감속) 등을 선택할 수 있습니다.
  • 지연 시간: 트랜지션이 시작되기 전 대기하는 시간.

다음은 호버 시 배경색과 그림자, 모서리 둥글기가 부드럽게 변경되는 카드 컴포넌트 예제입니다.

.interactive-card {
  width: 200px;
  height: 120px;
  background-color: #f0f4f8;
  border-radius: 8px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  /* 모든 속성 변화에 0.4초 동안 ease-in-out 타이밍 적용 */
  transition: all 0.4s ease-in-out;
}

.interactive-card:hover {
  background-color: #d9e2ec;
  border-radius: 16px;
  box-shadow: 0 10px 15px rgba(0, 0, 0, 0.2);
}

요소 이동 방식의 차이와 성능 최적화

요소의 위치를 이동시킬 때 전통적인 top, left 속성과 CSS3의 transform: translate()를 사용하는 것에는 근본적인 렌더링 성능 차이가 있습니다.

top이나 left를 변경하면 브라우저는 페이지의 레이아웃을 다시 계산하는 재배치(Reflow)와 화면을 다시 그리는 재그리기(Repaint)를 모두 수행해야 합니다. 반면, transform 속성은 레이아웃 재계산 없이 GPU 가속을 통한 합성(Composite) 단계에서만 처리되므로 훨씬 부드럽고 성능이 우수합니다.

translate의 기본 문법은 다음과 같습니다. (X축 오른쪽, Y축 아래쪽이 양의 방향입니다.)

/* X축과 Y축 동시 이동 */
transform: translate(x, y);

/* 단일 축 이동 */
transform: translateX(x);
transform: translateY(y);

/* 요소 자체 크기의 비율(%)로 이동 (중앙 정렬 등에 유용) */
transform: translate(50%, 50%);

다음은 자바스크립트를 활용해 클래스를 토글하여 요소를 이동시키는 예제입니다.

.draggable-item {
  width: 80px;
  height: 80px;
  background-color: #3182ce;
  /* 초기 위치와 트랜지션 설정 */
  transform: translate(0, 0);
  transition: transform 0.8s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.draggable-item.is-moved {
  /* X축 150px, Y축 100px 이동 */
  transform: translate(150px, 100px);
}
<div class="draggable-item"></div>
const item = document.querySelector('.draggable-item');
setTimeout(() => {
  item.classList.add('is-moved');
}, 1000);

요소 크기 조절과 레이아웃 영향 최소화 (Scale)

요소의 크기를 변경할 때 widthheight를 직접 수정하면 재배치(Reflow)가 발생하여 주변 요소들이 밀리게 됩니다. 하지만 transform: scale()을 사용하면 재배치를 방지할 수 있으며, 주변 레이아웃에 영향을 주지 않고 요소의 정중앙을 기준으로 확대/축소됩니다. (기준점은 transform-origin으로 변경 가능합니다.)

/* X축과 Y축 비율 설정 */
transform: scale(x, y);

/* X, Y축 동일한 비율로 설정 */
transform: scale(ratio);

다음은 페이지네이션 버튼에 마우스를 올렸을 때 부드럽게 확대되는 인터랙션 예제입니다.

.pagination-container {
  display: flex;
  gap: 12px;
}

.page-btn {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #cbd5e0;
  border-radius: 50%;
  cursor: pointer;
  transition: transform 0.2s ease, background-color 0.2s ease;
}

.page-btn:hover {
  transform: scale(1.25);
  background-color: #ebf8ff;
}
<div class="pagination-container">
  <div class="page-btn">1</div>
  <div class="page-btn">2</div>
  <div class="page-btn">3</div>
  <div class="page-btn">4</div>
</div>

요소 회전과 화살표 애니메이션 (Rotate)

transform: rotate()는 요소를 지정된 각도만큼 회전시킵니다. 아코디언이나 드롭다운 메뉴의 화살표 방향을 전환할 때 유용하게 사용됩니다. 여러 변환 함수는 공백으로 구분하여 동시에 적용할 수 있습니다.

/* 각도(deg)만큼 회전 */
transform: rotate(deg);

다음은 드롭다운 토글 버튼의 호버 상태에 따라 화살표의 방향이 회전하는 예제입니다.

.dropdown-toggle {
  position: relative;
  width: 200px;
  padding: 10px 15px;
  border: 1px solid #a0aec0;
  border-radius: 6px;
  cursor: pointer;
}

.dropdown-toggle::after {
  content: "";
  position: absolute;
  right: 15px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid #4a5568;
  border-bottom: 2px solid #4a5568;
  /* 초기 상태: 아래쪽 화살표 */
  transform: translateY(-75%) rotate(45deg);
  transition: transform 0.3s ease;
}

.dropdown-toggle:hover::after {
  /* 호버 시: 위쪽 화살표로 회전 및 위치 미세 조정 */
  transform: translateY(-25%) rotate(-135deg);
}
<div class="dropdown-toggle">메뉴 선택</div>

태그: CSS3 CSS-Transition CSS-Transform web-performance UI-Animation

8월 22일 16:14에 게시됨