인터랙션

[Image Compare Slider] before/after 두 이미지 가르기

드래그·터치·키보드로 before/after 두 이미지를 가르는 클래식 비교 컴포넌트. clip-path inset + Pointer Events + role="slider".

ReactTypeScriptPointer Eventsclip-pathARIA
라이브 데모
새 탭에서 열기
데모 불러오는 중…

제작 과정

한 줄 요약

같은 영역의 before/after 두 이미지를 가운데 핸들로 가르는 클래식 비교 컴포넌트. clip-path: inset() + Pointer Events로 라이브러리 없이 60줄이면 충분하다.

이럴 때 필요해요

보정 전후, 리디자인 시안 비교, 위성지도 변경 사항 등 "같은 영역의 두 상태"를 한눈에 보여줘야 할 때. 두 장을 따로 나열하면 차이가 직관적으로 안 들어오고, 가운데 핸들을 끌어 가르는 패턴이 가장 빠르게 차이를 인지시킨다.

어떻게 동작하나

  1. 같은 이미지를 두 번 렌더하고 위쪽에만 filter: grayscale(1)·sepia(0.7) 등을 걸어 "after"를 흉내 — 보정본을 따로 준비할 필요 없이 네트워크 요청 1회로 끝.
  2. 위에 덮는 원본을 clip-path: inset(0 (100-X)% 0 0)로 왼쪽부터 X%만 노출. width+overflow-hidden보다 레이아웃을 안 흔들고 composite만 갱신돼 깔끔.
  3. 컨테이너에 Pointer Events 핸들러를 달고 down 시점에 setPointerCapture — 커서가 박스 밖으로 나가도 이벤트가 끊기지 않고, 마우스·터치·펜이 단일 코드로 처리된다.
  4. 핸들에 role="slider"+aria-valuenow+tabIndex를 줘 ←/→ 2%, Shift+←/→ 10%, Home/End로 키보드만으로도 다룰 수 있게.

놓치기 쉬운 것

  • Safari iOS는 이미지가 매우 크면 clip-path: inset() 갱신 시 페인트가 튄다 — 1200px 이상 원본은 리사이즈해 쓰는 게 안전.
  • 모바일은 cursor: ew-resize가 의미 없으니 시각적인 "핸들 같음"이 더 중요 — 흰 원 + 좌우 셰브론으로 표시.
  • 키보드 step을 1%로 너무 작게 하면 큰 화면에서 도달이 느리다. 2% + Shift 10%가 체감상 자연스럽다.
  • touch-action: pan-y — 전체를 none으로 막으면 페이지 세로 스크롤이 죽는다. 가로만 슬라이더가 가져가게.

이런 곳에 써요

  • 이커머스 상품 상세 — "AS 전후", "세탁 전후" 비교
  • 지도·이미지 분석 도구 — 시점별·필터별 비교
  • 디자인 시안 리뷰 — Before/After 한 화면 비교

소스 코드

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

export const metadata: Metadata = {
  title: "이미지 비교 슬라이더 (데모)",
  description:
    "드래그·터치·키보드로 가운데 핸들을 움직여 before/after 두 이미지를 가르는 비교 슬라이더. clip-path inset + Pointer Events + role=\"slider\"로 접근성까지.",
  robots: { index: false, follow: false },
};

export default function Page() {
  return <ImageCompareSliderDemo />;
}
74조회수

댓글