모션은(는) 무엇을 하나요?
모션은 변화를 설명하고 입력을 확인합니다. 둘 중 하나도 하지 않는다면 장식이며 이유가 필요합니다.
1. 애니메이션을 적용해야 하는가?
| 사용자가 보는 빈도 | 결정 |
|---|---|
| 하루 100회 이상 (단축키, 팔레트 전환, 타이핑) | 절대 애니메이션 없음 |
| 수십 회 (호버, 리스트 탐색, 탭) | 아주 작게 또는 없음 (150ms 미만의 색상/불투명도) |
| 가끔 (모달, 드로어, 토스트, 드롭다운) | 표준 트랜지션 |
| 드물게 (온보딩, 성공, 첫 방문 히어로) | 즐거움을 위한 여유 |
키보드로 트리거된 동작에는 절대 애니메이션을 적용하지 마십시오.
2. 이징 (Easing)
- 들어오거나 나갈 때: 강한 ease-out
cubic-bezier(.23, 1, .32, 1). - 화면에서 움직일 때: ease-in-out
cubic-bezier(.77, 0, .175, 1). - 드로어/시트:
cubic-bezier(.32, .72, 0, 1). - 색상/호버:
ease. 지속적인 움직임 (마키, 진행률):linear. - UI에는 절대
ease-in을 사용하지 마십시오. 사용자가 보고 있는 순간에 지연되는 느낌을 줍니다.
3. 지속 시간 (Duration)
누름 100-160ms · 툴팁 125-200ms · 드롭다운 150-250ms · 모달/드로어 200-400ms · 마케팅 히어로 최대 800ms. 종료는 입장보다 약 20% 더 빠릅니다. UI 모션은 300ms 미만으로 유지합니다.
4. 크래프트 규칙
transform과opacity만 애니메이션합니다. 절대width,height,top,left또는transition: all를 사용하지 마십시오.scale(0)에서 나타나는 것은 없습니다.scale(.95)+opacity: 0에서 시작하십시오.- 팝오버와 메뉴는 트리거에서 확장됩니다 (
transform-origin을 트리거에 설정). 모달은 중앙에 유지됩니다. - 버튼:
:active { transform: scale(.97) }(120ms 트랜지션 적용). - 툴팁: 첫 번째는 지연(~400ms)시키고, 인접한 것은 즉시 엽니다.
- 리스트를 아이템당 30-50ms씩 스태거링하며, 총합을 400ms 미만으로 제한합니다.
- 스크롤 리빌: 페이지당 최대 한 번, 작은 거리(8-16px), 한 번만 실행합니다. 모든 섹션에 적용하지 마십시오.
- 스프링 (Motion/Framer, React Spring): 드래그, 제스처 및 중단 가능한 움직임에 사용:
{ type: "spring", duration: .4, bounce: .15 }. 바운스는 0.1-0.3으로 유지하고, 재미있는 표면에만 사용하십시오. - 단순한 입장/퇴장에는 CSS 트랜지션과
@starting-style을 선호하고, 페이지/상태 변형에는 View Transitions API를, 제스처나 시퀀스가 필요할 때만 JS 라이브러리를 사용하십시오.
5. 축소 모션 (필수)
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .01ms !important;
animation-iteration-count: 1 !important;
transition-duration: .01ms !important;
scroll-behavior: auto !important;
}
}
불투명도 변경과 상태 색상은 유지하고, 움직임, 시차 및 흔들림은 제거합니다.
리뷰 형식
모션 코드를 리뷰할 때는 표로 답변하십시오: | Before | After | Why |, 이슈당 한 행씩.