Skip to content

Comparison

import { Comparison } from '@delightstack/components';
Before After Photo A Photo B
View code
<script>
import { Comparison } from '@delightstack/components';
</script>
<Comparison
before="/images/photo-original.jpg"
after="/images/photo-edited.jpg"
label_before="Photo A"
label_after="Photo B"
snaps={[50]}
/>
Original photo Edited photo with filters applied Before After
View code
<Comparison
before="/images/photo-original.jpg"
after="/images/photo-edited.jpg"
before_alt="Original photo"
after_alt="Edited photo with filters applied"
/>
Before After Version 1 Version 2
View code
<Comparison
before="/images/design-v1.png"
after="/images/design-v2.png"
label_before="Version 1"
label_after="Version 2"
/>
Before After
View code
<Comparison
before="/images/before.jpg"
after="/images/after.jpg"
show_labels={false}
/>

The divider moves up and down instead of left and right.

Before After Before After
View code
<Comparison
before="/images/before.jpg"
after="/images/after.jpg"
vertical
/>

Bind to the position prop to control or read the slider position (0-100).

Before After Before After

Position: 50%

View code
<script>
let position = $state(50);
</script>
<Comparison
before="/images/before.jpg"
after="/images/after.jpg"
bind:position
/>
<p>Position: {position}%</p>

Define snap points that the divider magnetically locks to. The divider uses springy magnetic gravity near snap points and a rubber-band effect when dragged past the edges.

Before After Before After

Position: 50%

View code
<Comparison
before="/images/before.jpg"
after="/images/after.jpg"
snaps={[25, 50, 75]}
/>
View code
<Comparison skeleton={loading} before={before_url} after={after_url} />
PropTypeDefaultDescription
beforestringrequiredBefore image URL
afterstringrequiredAfter image URL
before_altstring'Before'Before image alt text
after_altstring'After'After image alt text
positionnumber50Divider position (0-100), bindable
verticalbooleanfalseVertical orientation (divider moves up/down)
show_labelsbooleantrueShow before/after labels
label_beforestring'Before'Before label text
label_afterstring'After'After label text
skeletonbooleanfalseShow loading skeleton
snapsnumber[][]Snap points the divider magnetically locks to (0-100)
idstringautoElement ID
classstring''Additional CSS classes
EventDetailDescription
onchange{ position: number }Fired when the divider position changes
VariableDefaultDescription
--cmp-radiusvar(--radius-xl, 20px)Corner radius of the container (set 0 to square it off)
--cmp-aspect16 / 9Aspect ratio of the skeleton placeholder — set it to match the real images so the skeleton ↔ loaded swap doesn’t shift
  • Divider handle has role="slider" with aria-valuenow, aria-valuemin="0", and aria-valuemax="100"
  • aria-label="Comparison slider" on the handle
  • Both images have descriptive alt text
  • Full keyboard support:
    • Tab to focus the handle
    • Arrow Left/Right (horizontal) or Arrow Up/Down (vertical) moves in 1% increments
    • Shift+Arrow moves in 10% increments
    • Home moves to 0%
    • End moves to 100%
  • Click anywhere on the image to jump the divider to that position
  • touch-action: none prevents scroll interference on mobile
  • Images have draggable="false" to prevent native drag behavior