Image Compare
A before/after image comparison slider. Drag (or hover) to reveal one image over another, horizontally or vertically, with optional labels, a custom handle, and a loading skeleton. Responsive out of the box.
A before/after image comparison slider. Two images are stacked in the same
box; a draggable divider clips the top image to reveal the one beneath.
Drag the handle — or set hover to reveal on pointer move — to wipe between
them. The container always fits the parent width and derives its height from
the images' aspect ratio, so it stays responsive.
It is self-contained: a single ResizeObserver tracks the width and
pointer-capture drives the slider. Styling is plain Tailwind classes, with
only the dynamic values (height, clip-path, slider offset) applied inline,
and the default handle uses lucide-react chevrons. Labels, a custom
handle, and a loading skeleton are all optional.
Installation
One-time setup: add the @ikui registry to your components.json.
{
"registries": {
"@ikui": "https://ik-ui.pages.dev/r/{name}.json"
}
}Then install the component:
pnpm dlx shadcn@latest add @ikui/image-compareUsage
import { ImageCompare } from "@/components/image-compare";<ImageCompare
leftImage="/before.png"
rightImage="/after.png"
leftImageLabel="Before"
rightImageLabel="After"
/>Examples
Vertical
Set vertical to compare top vs. bottom instead of left vs. right. The
leftImage becomes the top image and the rightImage the bottom one.
Fill the parent
By default the container derives its height from the images' aspect ratio.
Set fill to make it follow the parent's height instead — the parent must
have a definite height. Pair it with objectFit="contain" to letterbox
images so they are never cropped, regardless of how the parent's size
matches the images' ratio.
Props
| Prop | Type | Default |
|---|---|---|
leftImage | string | - |
rightImage | string | - |
vertical | boolean | false |
hover | boolean | false |
aspectRatio | "taller" | "wider" | "taller" |
fill | boolean | false |
objectFit | "cover" | "contain" | "cover" |
sliderPositionPercentage | number | 0.5 |
onSliderPositionChange | (position: number) => void | - |
leftImageLabel | ReactNode | - |
rightImageLabel | ReactNode | - |
leftImageAlt | string | "" |
rightImageAlt | string | "" |
handle | ReactNode | - |
skeleton | ReactNode | - |
className | string | - |
ImageCompare forwards a ref to its outermost container element
(HTMLDivElement), so you can measure or scroll it.

