인터랙션

숫자가 굴러가는 오도미터 카운터

각 자릿수가 0~9 세로 스트립으로 굴러가 제자리를 찾는 기계식 카운터. transform만 써서 JS 애니메이션 루프 없이 부드럽게 동작합니다.

ReactTypeScriptCSS transform/transitionTailwind CSSprefers-reduced-motion
라이브 데모
새 탭에서 열기
데모 불러오는 중…

제작 과정

한 줄 요약

각 자릿수를 0~9가 세로로 쌓인 스트립으로 두고 translateY로 굴려, JS 애니메이션 루프 없이 transform만으로 굴러가는 숫자 카운터를 만듭니다.

이럴 때 필요해요

대시보드 KPI, 가격, 좋아요조회수처럼 "숫자가 바뀌었다"를 강조하고 싶을 때, 그냥 텍스트를 교체하면 변화가 눈에 안 들어옵니다. 단순 카운트업은 텍스트만 빠르게 증가시키지만, 오도미터는 자릿수 하나하나가 물리적으로 굴러가 "기계가 돌아가는" 인상을 줍니다. 시선을 정확히 그 숫자로 끌고 싶을 때 답이 됩니다.

어떻게 동작하나

  1. 값을 토큰으로 분해 숫자는 굴러가는 자릿수, 부호통화콤마소수점은 고정 글리프로 구분합니다.

  2. 각 자릿수는 overflow-hidden 창 안에 0~9를 세로로 쌓고, 현재 숫자 d만큼 translateY(-d em)로 이동합니다. 값이 바뀌면 CSS transition이 새 위치로 굴립니다.

  3. 자리별로 transition-delay를 줘(낮은 자리 먼저, 높은 자리 나중) 실제 계기판처럼 시차를 둡니다.

놓치기 쉬운 것

  • key를 왼쪽이 아니라 오른쪽(1의 자리) 기준으로 매겨야 99100처럼 자릿수가 늘 때 기존 열이 리마운트로 튀지 않습니다.

  • tabular-nums + 고정 폭이 없으면 1과 8의 너비 차이로 숫자가 좌우로 흔들립니다.

  • prefers-reduced-motion 사용자에겐 transition을 끄고 즉시 스냅해야 합니다.

이런 곳에 써요

  • 대시보드 지표 카드, 가격 토글(월연) 전환 표시

  • 좋아요조회수재고 수량처럼 실시간으로 바뀌는 카운터

소스 코드

· 데모 페이지에서 자동 추출
import type { Metadata } from "next";
import { NumberOdometer } from "./-components/NumberOdometer";

export const metadata: Metadata = {
  title: "숫자 오도미터 (데모)",
  description:
    "각 자릿수가 0~9 세로 스트립으로 굴러가는 기계식 카운터. translateY + 자리별 시차(stagger) + 천 단위 구분자·통화 기호, prefers-reduced-motion 대응.",
  robots: { index: false, follow: false },
};

export default function Page() {
  return (
    <main className="flex min-h-[100dvh] items-center justify-center bg-gradient-to-br from-slate-50 via-white to-violet-50/40">
      <NumberOdometer />
    </main>
  );
}
26조회수

댓글