한 줄 정답 — 변화시킬 요소에
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 버튼 만들기#
색과 살짝 떠오르는 움직임을 함께 주는, 가장 많이 쓰는 패턴이다.
- 버튼의 평소 상태에
transition을 건다(바꿀 속성과 시간 지정). :hover에서 바뀔 값만 적는다.- 위치 변화는
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·left나 width·height를 직접 애니메이션하면 매 프레임 레이아웃이 다시 계산돼 끊길 수 있지만, transform과 opacity는 레이아웃을 건드리지 않아 부드럽습니다. 살짝 떠오르는 효과는 transform: translateY(-2px)가 정석입니다.
관련 글#
transition은 결국 "상태가 바뀔 때 부드럽게"를 담당한다. 무엇을 어떻게 배치하느냐(레이아웃)와 함께 익히면 화면에 자연스러운 움직임을 입히기 쉬워진다.
- position absolute relative 차이 — 5가지 한눈에
- CSS flexbox 정렬 — 주축·교차축으로 한 번에 이해하기
- display 속성 — block, inline, inline-block의 정확한 차이