Components / Data display

ImageCompare

Drag a divider across two images to see what changed.

Install

npx shadcn@latest add https://irisui.dev/r/image-compare.json
import { ImageCompare } from "@/components/iris/image-compare/image-compare";
Registry item image-compareBrings in foundationRegistry JSON

Preview

ImageCompare

Two images stacked in one frame with a draggable divider, so people can wipe between a before and an after.

When to use

  • Showing what changed: a revised floor plan, a redesign, a photo edit.
  • When the two images share the same framing and the difference is spatial.
  • Use Carousel for several unrelated images, and side-by-side images (two Card media) when people need to see both whole at once.

Usage

import { ImageCompare } from "@/components/iris/image-compare/image-compare";

h(ImageCompare, {
  before: h("img", { src: "/plans/kypseli-current.svg", alt: "Current floor plan" }),
  after: h("img", { src: "/plans/kypseli-revised.svg", alt: "Revised floor plan" }),
  labels: ["Current", "Revised"],
  label: "Reveal the revised floor plan",
  aspectRatio: "16 / 9",
});

Props

Prop Type Default Description
before ReactNode — (required) Original, on the left (or top). Pass an element with its own alt text; it is sized to cover the frame.
after ReactNode — (required) Result, on the right (or bottom).
position / defaultPosition / onPositionChange number / number / (p) => void — / 50 Divider position in percent, controlled or uncontrolled.
orientation "horizontal" | "vertical" "horizontal" Vertical stacks top and bottom; switching swings the divider a quarter turn.
labels [string, string] | false ["Before", "After"] Captions over each side; they fade as the divider reaches them. false hides them.
label string "Before and after" Accessible name of the divider.
aspectRatio string "3 / 2" Frame proportions as a CSS aspect-ratio.
className string — Extra class on the root.

Notes

  • The divider is a focusable slider: arrow keys step 1% (Shift for 10%), Home/End reveal one side fully, double-clicking the handle springs it back to the middle.
  • Dragging follows 1:1 with a rubber-band past the edges; a press on the image springs the divider there. On touch it waits for a sideways drag so the page still scrolls.
  • Any element works for each side (img, picture, video, inline SVG).