모션
모션은 두 갈래다. 상태 전환(hover · 열림 · 눌림)은 Tailwind transition으로 150~300ms 안에 끝내고, 데이터 움직임(차트 등장 · 롤링 숫자)은 token 시간으로 처음 볼 때와 값이 바뀔 때만 움직인다. 데이터 움직임의 값은 시스템이 정하고, 앱은 화면 경계에서 끈다.
살아있는 예시 · hover · 탭 해보기
전환 대상 · property
transition-colors색 전환: hover·focus. 가장 흔함(버튼·링크·인풋).
transition-transform이동·회전·확대: 토글 화살표·살짝 커지는 카드.
transition기본 묶음(색·그림자·투명도·transform 등 자주 쓰는 속성).
transition-none전환 끔: 즉시 반영해야 할 때.
transition-all은 피한다: 의도치 않은 속성까지 전환돼 성능·버그를 부른다. 필요한 속성만 지정.
지속 시간 · duration
duration-150빠름: 색·작은 hover. 즉각적인 느낌.
duration-200기본: 대부분의 인터랙션.
duration-300느림: 패널 열림 등 큰 이동.
이징 · easing
ease-out빠르게 시작→천천히 멈춤. 등장(나타날 때)에 권장: 가장 자연스럽다.
ease-in천천히 시작→빠르게. 퇴장(사라질 때)에.
ease-in-out양끝 부드럽게. 이동·상태 전환.
원칙
- 상태 전환은 짧게(150–300ms). 길면 느리게 느껴진다.
- 색 전환 위주. 대부분
transition-colors면 충분하다. - 데이터 움직임은 두 순간만. 처음 볼 때와 값이 바뀔 때. 반복 · hover · 스크롤마다 다시 움직이지 않는다.
- 접근성: 움직임 줄이기 설정이 언제나 우선한다. 상태 전환은
motion-reduce:transition-none, 데이터 움직임은 component가 스스로 멈춘다.
데이터 움직임 · 차트와 숫자
막대는 기준선에서 자라고, 선 · 영역은 왼쪽부터 드러나고, 도넛 · 게이지 · 링의 호는 0에서 값까지 돌고, RollingNumber 숫자는 0~9 띠가 굴러 멈춘다. 처음 화면에 보이는 차트는 바로, 화면 밖 차트는 스크롤해 들어올 때 움직인다. 모두 CSS 애니메이션이라 서버 렌더 그대로이고, JS가 없거나 늦으면 그려질 때 움직인다.
5월
매출2,400
6월
매출2,900
7월
매출2,600
8월
매출3,300
9월
매출4,100
10월
매출1,019
데이터 움직임 token
--chart-motion-duration차트가 처음 그려질 때(막대 자람 · 선 드러남 · 호 돎)와 값이 바뀔 때의 시간. 순차 등장 간격도 이 시간에 비례한다.
--chart-motion-ease차트 곡선. 기본은 빠르게 시작해 천천히 멈추는 cubic-bezier(0.22, 1, 0.36, 1).
--number-motion-durationRollingNumber 숫자 칸이 0 에서(처음) 또는 이전 숫자에서(값이 바뀔 때) 굴러 멈추는 시간.
--number-motion-ease숫자 곡선. 기본은 차트와 같다.
시스템별 값
데이터 움직임은 component 옵션이 아니라 시스템이 정한다. 위성 시스템은 네 token을 반드시 정하고(정하지 않으면 conformance 검사가 실패한다), 근거를 token 옆 주석에 적는다. 0s는 그 움직임이 없는 시스템이다.
Polaris기본. 빠르게 시작해 천천히 멈춘다.
Betelgeuse번짐 없는 offset shadow 처럼 움직임도 부드럽게 이어지지 않고 네 번에 끊어 자란다. 숫자 띠는 끊으면 자리가 어긋나므로 짧은 곡선으로 굴린다.
Vega짧은 transition 을 쓰는 시스템이라 Polaris 의 절반 남짓으로 짧게 움직인다.
Muse매거진 지면의 숫자는 본문 타이포그래피의 일부라 굴리지 않는다. 차트는 느리고 고르게 드러난다.
Orbit터미널 · 인프라 도구의 기계적인 인상에 맞춰 곡선 없이 일정한 속도로 짧게 움직인다.
Lumen차분한 상태 피드백을 위해 Polaris 보다 길고 양끝이 느린 곡선으로 천천히 드러난다. */ --dx-radius-scale: 1.5; --dx-density: 1.125; --dx-border-width: 1px; --dx-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.04), 0 4px 12px -4px rgb(0 0 0 / 0.08); --dx-shadow-lg: 0 24px 48px -16px rgb(0 0 0 / 0.2); --dx-shadow-xl: 0 32px 64px -20px rgb(0 0 0 / 0.26); --dx-font-sans: "Pretendard", var(--font-geist-sans, sans-serif); --dx-focus-color: var(--accent); --dx-focus-width: 2px; --dx-focus-offset: 0px; --dx-heading-weight: 600; --dx-heading-tracking: normal; /* 데이터 움직임(차트 등장 · 롤링 숫자): 차분한 피드백 화면이라 길게, 양끝을 느리게 움직인다.
Atlas금융 · 공공 업무 화면이라 차트는 짧게 움직이고 숫자는 굴리지 않는다. 숫자가 구르는 동안 틀린 금액이 잠깐이라도 보이면 안 된다.
Lyra개발 협업 목록은 별 · 이슈 같은 개수가 자주 바뀌어 굴리면 산만하므로 숫자는 굴리지 않고, 차트는 짧게만 움직인다.
Ceres커머스 · 예약 화면의 친근한 인상에 맞춰 막대 · 호 · 숫자가 목표를 살짝 넘었다가 돌아와 멈춘다.
Sirius의료 · 공공 서비스의 접근성 우선 시스템이라 차트와 숫자 모두 움직이지 않는다. 전정 장애나 인지 부담이 있는 사용자가 OS 설정을 몰라도 같은 화면을 받는다.
Nocturne엔터테인먼트 화면이라 Polaris 와 같은 값으로 차트와 숫자를 모두 움직인다(물려받지 않고 명시한다).
화면 경계에서 끄기
앱은 component마다 끄지 않고, 움직임이 과업과 맞지 않는 화면이나 영역을 감싼 요소에서 두 duration을 0s로 덮는다. 순차 등장 지연도 duration에 비례하므로 0s면 요소가 시차 없이 바로 보인다.
실시간 갱신몇 초마다 값을 새로 받는 관제 · 모니터링 화면. 값이 바뀔 때마다 숫자가 굴러 읽기 어렵다.
인쇄 · 내보내기PDF · 이미지로 내보내는 화면. 캡처 시점에 막대가 덜 자란 채 찍힐 수 있다.
숫자가 많은 표한 화면에 굴러가는 숫자가 수십 개면 시선이 흩어지고 요소 계산이 늘어난다. 표 안 숫자는 굴리지 않는다.
확인 · 결제 단계금액을 확정하는 화면. 구르는 동안 다른 금액이 잠깐이라도 보이지 않게 한다.
/* 앱 CSS: 이 영역 안의 차트 · 숫자는 움직이지 않는다 */
.live-monitor {
--chart-motion-duration: 0s;
--number-motion-duration: 0s;
}