한 줄 정답 — 변화시킬 요소에 transition: 속성 시간;을 미리 걸어두고, :hover 같은 상태에서 그 속성 값을 바꾸면 변화가 부드럽게 이어진다. 예: button { transition: background-color 0.2s; } button:hover { background-color: #2563eb; }. transition평소 상태에 두는 것이 핵심이고, duration이 없으면(0s) 아무 변화도 보이지 않는다.

핵심 요약#

  • transition상태가 바뀔 때(hover, focus, 클래스 토글 등) 두 값 사이를 시간에 걸쳐 보간하는 속성이다.
  • 네 부분으로 나뉜다: 무엇을(transition-property) · 얼마나 오래(duration) · 어떤 가속으로(timing-function) · 언제부터(delay).
  • 단축으로 transition: transform 0.3s ease 0s;처럼 한 줄에 적는다. 시간 값 중 첫 번째가 duration, 두 번째가 delay다.
  • transition변화 후 상태가 아니라 평소(기본) 상태에 둔다. 그래야 들어갈 때도 나올 때도 부드럽다.
  • display, height: auto 같은 값은 보간되지 않아 흔히 "transition이 안 먹는" 원인이 된다.

CSS transition 사용법, 네 가지 속성부터#

transition은 한 속성의 값이 바뀔 때 그 사이를 부드럽게 채워주는 기능이다. 색이 휙 바뀌는 대신 서서히 변하고, 크기가 점프하는 대신 자라난다. 트리거는 보통 :hover·:focus나 자바스크립트로 붙였다 떼는 클래스다.

핵심은 두 가지다. 첫째, 변화시킬 속성을 미리 알려줘야 한다. 둘째, 얼마 동안 변할지(duration) 정해야 한다. 이 둘이 없으면 변화는 즉시 일어난다.

.box {
  background-color: #e5e7eb;
  transition: background-color 0.3s; /* 평소 상태에 둔다 */
}

.box:hover {
  background-color: #2563eb;         /* 바뀔 값만 지정 */
}

transition.box:hover 쪽이 아니라 .box에 둔 점을 보자. 이렇게 해야 마우스를 올릴 때도, 뗄 때도(원래 값으로 돌아갈 때도) 똑같이 부드럽다. :hover에만 두면 들어갈 때만 부드럽고 나올 때는 툭 끊긴다.

transition-property — 무엇을 바꿀까#

애니메이션할 속성 이름을 적는다. 여러 개면 쉼표로 나열하고, 전부면 all을 쓴다.

.card {
  transition-property: transform, box-shadow; /* 두 속성만 */
}

transition: all은 편하지만, 의도치 않은 속성까지 따라 변해 끊김이 생기거나 성능에 부담이 될 수 있다. 바꿀 속성을 명시하는 편이 안전하다.

transition-duration — 얼마나 오래#

변화에 걸리는 시간이다. s(초) 또는 ms(밀리초)로 적는다. 이 값이 없으면 기본이 0s라 아무것도 보이지 않는다 — transition이 "안 먹는" 가장 흔한 이유다.

.box {
  transition-duration: 0.2s; /* = 200ms */
}

버튼·작은 UI는 0.15s~0.3s가 자연스럽다. 너무 길면(0.6s 이상) 답답하게 느껴진다.

transition-timing-function — 어떤 가속으로#

변화의 속도 곡선이다. 같은 시간이라도 곡선에 따라 느낌이 다르다.

느낌
ease (기본)빠르게 시작해 끝에서 감속 — 가장 무난
linear처음부터 끝까지 등속
ease-in천천히 시작
ease-out천천히 끝 — UI 진입에 자연스러움
ease-in-out양 끝 모두 부드럽게
cubic-bezier(...)곡선을 직접 지정
.box {
  transition: transform 0.3s ease-out;
}

transition-delay — 언제부터#

변화가 시작되기까지 기다리는 시간이다. 기본은 0s. 여러 요소를 순차로 등장시키는 등에 쓴다.

.box {
  transition: opacity 0.3s ease 0.1s; /* 0.1초 뒤 시작 */
}

단축 속성으로 한 줄에#

위 네 개를 transition 하나로 묶을 수 있다. 순서는 속성 · duration · timing-function · delay이고, 시간 값이 둘이면 앞이 duration, 뒤가 delay다.

.box {
  transition: background-color 0.3s ease 0s;
}

/* 여러 속성을 각각 다르게 */
.card {
  transition: transform 0.3s ease, box-shadow 0.2s ease;
}

단계별로 따라하기 — hover 버튼 만들기#

색과 살짝 떠오르는 움직임을 함께 주는, 가장 많이 쓰는 패턴이다.

  1. 버튼의 평소 상태transition을 건다(바꿀 속성과 시간 지정).
  2. :hover에서 바뀔 값만 적는다.
  3. 위치 변화는 margin·top 대신 transform을 쓴다(부드럽고 성능에 유리).
.btn {
  padding: 12px 20px;
  background-color: #2563eb;
  color: #fff;
  border: none;
  border-radius: 8px;
  transition: background-color 0.2s ease, transform 0.2s ease;
}

.btn:hover {
  background-color: #1d4ed8;
  transform: translateY(-2px); /* 살짝 떠오름 */
}

.btn:active {
  transform: translateY(0);    /* 누르면 제자리 */
}

transform과 함께 쓰면 좋은 이유#

위치·크기 변화를 줄 때 left/top이나 width/height를 직접 애니메이션하면 브라우저가 매 프레임 레이아웃을 다시 계산해 끊길 수 있다. 반면 transform(이동·확대·회전)과 opacity는 레이아웃을 건드리지 않아 부드럽다.

.thumb {
  transition: transform 0.3s ease;
}
.thumb:hover {
  transform: scale(1.05); /* 5% 확대 */
}

transform으로 요소를 움직일 때 기준이나 겹침이 헷갈린다면 position absolute relative 차이에서 좌표·쌓임 맥락을 함께 보면 이해가 빠르다.

애니메이션되는 속성, 안 되는 속성#

모든 속성이 부드럽게 변하지는 않는다. 두 값 사이를 숫자로 보간할 수 있는 속성만 애니메이션된다.

  • 잘 되는 것: color·background-color, opacity, transform, width·height(고정값), margin·padding, box-shadow, border-color 등.
  • 안 되는 것: display(상태값이라 중간이 없음), height: auto처럼 계산값이 auto인 경우, 일부 키워드 전용 속성.

display: none ↔ block을 부드럽게 펼치고 싶을 때 흔히 막히는데, display는 보간되지 않기 때문이다. 보통은 opacity(+transform이나 max-height)로 우회한다. display 자체와 display 속성의 차이를 먼저 이해해 두면 왜 안 되는지 와닿는다.

CSS transition이 안 먹을 때 — 흔한 원인#

대부분 다음 중 하나다.

  • duration이 없다. transition 속성에 시간을 안 적으면 기본 0s라 즉시 바뀐다. 가장 흔한 실수다.
  • transition:hover 쪽에만 뒀다. 평소 상태에 둬야 들어갈 때·나올 때 모두 부드럽다.
  • 애니메이션되지 않는 속성을 바꿨다. display 토글이 대표적. opacity로 바꿔 본다.
  • height: auto로 펼치려 한다. auto는 보간 불가. max-height에 충분히 큰 고정값을 주는 식으로 우회한다.
  • 시작 값이 없다. 요소가 처음 나타나는 순간엔 "이전 값"이 없어 transition이 걸리지 않을 수 있다.

자주 묻는 질문#

Q. css transition이 안 먹을 때 가장 먼저 뭘 확인하나요?

A. transition시간(duration)이 들어갔는지 먼저 보세요. 시간이 없으면 기본값이 0s라 변화가 즉시 일어나 애니메이션이 보이지 않습니다. 그다음으로 transition:hover가 아니라 평소(기본) 상태에 뒀는지, 바꾸려는 속성이 애니메이션 가능한 속성인지 확인합니다.

Q. transition-duration과 transition-delay는 어떻게 구분하나요?

A. duration은 변화에 걸리는 시간, delay는 변화가 시작되기까지 기다리는 시간입니다. 단축 표기 transition: opacity 0.3s 0.1s에서는 앞의 0.3s가 duration, 뒤의 0.1s가 delay입니다. 시간 값이 하나면 그건 항상 duration입니다.

Q. transition을 all로 주면 안 되나요?

A. 동작은 하지만 권장하지 않습니다. transition: all은 바뀌는 모든 속성을 따라 애니메이션해 의도치 않은 끊김이나 성능 부담을 만들 수 있습니다. transform·opacity처럼 바꿀 속성을 명시하는 편이 안전하고 부드럽습니다.

Q. css hover 애니메이션에서 위치를 옮길 때 top·left와 transform 중 뭐가 낫나요?

A. transform이 낫습니다. top·leftwidth·height를 직접 애니메이션하면 매 프레임 레이아웃이 다시 계산돼 끊길 수 있지만, transformopacity는 레이아웃을 건드리지 않아 부드럽습니다. 살짝 떠오르는 효과는 transform: translateY(-2px)가 정석입니다.

관련 글#

transition은 결국 "상태가 바뀔 때 부드럽게"를 담당한다. 무엇을 어떻게 배치하느냐(레이아웃)와 함께 익히면 화면에 자연스러운 움직임을 입히기 쉬워진다.

더 알아보기#