Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelog
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone Select
Forms
Address InputCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowPost Listing WizardPricing PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAI Product PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePress PageProduct Tour PagePromo PageReferral PageResearch Report PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageSwitch PageTemplate Gallery PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Media

Image compare

Media

Image compare React component for Tailwind CSS v4

File SystemImage Cropper
Live props
Content
beforeAlt
afterAlt
showLabels
beforeLabel
afterLabel
label
State
defaultValue50%
Layout
orientation
aspectRatio
Behavior
mode
step
Appearance
handle
radius
color
Code
import ImageCompare from "@/components/ui/image-compare"

<ImageCompare />
  1. Home
  2. Components
  3. Media
  4. Image compare
Pro

Image compare React component for Tailwind CSS v4

v1.0.0·Added in 1.10.0

A before and after slider over two images or any two layers, for photo edits, AI image tools, redesigns and renovations.

Drag the handle, or anywhere on the image, to slide the divider: the before layer is revealed up to it and the after layer shows past it, following the pointer 1:1. Click or tap a spot and the divider springs there. The Before and After chips fade out while you drag and when the divider covers their corner. On a phone a sideways drag moves the divider while a vertical swipe still scrolls the page (the other way around when vertical), pinch zoom still works, and the handle has a 44px target that stays inside the frame at either end. In hover mode the divider follows a mouse without pressing; touch still drags. With the keyboard, Tab to the handle: the arrow keys move it by step, Shift moves ten steps, PageUp / PageDown move ten steps, Home / End jump to the edges, and a screen reader hears both shares.

Image compare is a Pro React component in the React media components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add image-compare, together with Motion presets, UIProvider, useControllableState and useMediaQuery and the npm package motion.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add image-compare

Pro item: the CLI needs a Pro account. See plans

Usage

Import ImageCompare from @/components/ui/image-compare.

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

export function RetouchPreview() {
  return (
    <ImageCompare
      before="/photos/street-raw.jpg"
      after="/photos/street-graded.jpg"
      beforeAlt="Street photo, unedited"
      afterAlt="Street photo, color graded"
      beforeLabel="Raw"
      afterLabel="Graded"
      onValueChange={(value) => console.log(value)}
    />
  )
}

Props

  • before*
    string | ReactNode

    The layer shown up to the divider: an image URL, or any node (a screenshot component, a canvas, a video).

  • after*
    string | ReactNode

    The layer shown past the divider, and the one that sizes the frame when aspectRatio is auto.

  • beforeAltdefault "Before"
    string

    Alt text of the before image (and its name in the slider's value text).

  • afterAltdefault "After"
    string

    Alt text of the after image.

  • value
    number

    The divider's position in percent from the left (or the top when vertical), when you control it.

  • defaultValuedefault 50
    number

    The starting position, uncontrolled.

  • onValueChange
    (value: number) => void

    Called when a drag ends, on a tap, on each key press and when the mouse leaves in hover mode. Never per frame.

  • orientationdefault "horizontal"
    "horizontal" | "vertical"

    horizontal splits left and right, vertical splits top and bottom.

  • modedefault "drag"
    "drag" | "hover"

    hover makes the divider follow a mouse without pressing (fine pointers only); touch always drags.

  • showLabelsdefault true
    boolean

    Chips naming each layer in its corner.

  • beforeLabeldefault "Before"
    ReactNode

    The before chip. Empty hides it.

  • afterLabeldefault "After"
    ReactNode

    The after chip. Empty hides it.

  • handledefault "arrows"
    "line" | "circle" | "arrows"

    The grip on the divider: a slim bar, a plain knob, or a knob with arrows. Every one is a 44px target.

  • radiusdefault "lg"
    "none" | "sm" | "md" | "lg"

    Corner radius of the frame: 0, 12, 16 or 24px.

  • aspectRatiodefault "16/10"
    string

    CSS aspect ratio of the frame. "auto" lets the after layer set the height.

  • colordefault "#ffffff"
    string

    The divider line (and the line handle), any CSS color.

  • stepdefault 1
    number

    Keyboard step in percent; Shift and PageUp / PageDown move ten steps. Drags and taps snap to it too.

  • labeldefault "Comparison position"
    string

    The slider's accessible name.

  • valueText
    (value: number) => string

    What a screen reader hears for a position. Default: "Before 50%, After 50%" with your label names.

  • classNames
    Partial<Record<"before" | "after" | "handle" | "line" | "label", string>>

    Classes for the before and after layers (a CSS filter on an image goes here), the knob, the divider line and both chips.

Parts

  • ImageCompareOrientation

    type

    "horizontal" | "vertical".

  • ImageCompareMode

    type

    "drag" | "hover".

  • ImageCompareHandle

    type

    "line" | "circle" | "arrows".

  • ImageCompareRadius

    type

    "none" | "sm" | "md" | "lg".

  • ImageCompareSlot

    type

    The keys of classNames.

Examples

Vertical

Top and bottom halves, a 4/3 frame and the md radius.

Hover mode

The divider tracks the mouse; the line handle keeps the photo clear.

Custom nodes

Two React nodes instead of images: the same dashboard in light and dark.

Controlled

A slider and buttons drive the divider; it springs to each new value.

Dependencies

motionmotionui-configuse-controllable-stateuse-media-query

Files

  • components/ui/image-compare.tsx

FAQ

Is the React Image compare component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Image compare?

Run npx wingo-ui@latest add image-compare. It also adds the Wingo UI items it builds on (Motion presets, UIProvider, useControllableState and useMediaQuery) and the npm package motion. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/image-compare.

How does Image compare behave on phones?

On a phone a sideways drag moves the divider while a vertical swipe still scrolls the page (the other way around when vertical), pinch zoom still works, and the handle has a 44px target that stays inside the frame at either end.

See also

Image CropperImage LightboxSliderDiff Viewer

More React media components

PDF ViewerStep PlayerQR CodeCarouselPowerPoint ViewerVideo Player
All 16 React media components
PreviousFile SystemNext Image Cropper
After
Before
BeforeAfter

Drag the handle, or click or tap anywhere on the photo. Arrow keys move 1%, Shift 10%.