Before and after slider for an AI image edit: HTML and CSS, no library

Show an original and its AI edit with a draggable divider using two stacked images, a clip-path and a range input. About 25 lines, no JavaScript framework.

5 min readSume
All posts

To compare an image with its AI edit, stack the two images in one box, clip the top one with clip-path: inset() and drive the clip from an <input type="range">. Dragging the slider changes one CSS variable, so there is no library, no canvas and the control works with a keyboard because it is a native input. The page below is about 25 lines.

For a before and after to mean anything, both images must have the same dimensions and framing. Edits through Sume's image endpoint with no aspect_ratio set on Ideogram 4.5 keep the source geometry, and other models document their own aspect_ratio behavior in the catalog, so check the output size before you publish a comparison.

What does each part do?

Slider parts, read 2026-10-04
PartJobNotes
Wrapper divFixes the box and sets position: relativeGive it the image's aspect ratio
Bottom imgThe edited imageAlways fully visible
Top imgThe originalClipped from the right by --pos
input rangeThe controlNative, keyboard-accessible, labelled

What is the page?

Replace the two file names with your original and the downloaded edit. Add real alt text that describes what changed.

<!doctype html>
<meta charset="utf-8">
<style>
  .cmp { --pos: 50%; position: relative; max-width: 720px; aspect-ratio: 4 / 5; }
  .cmp img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
  .cmp .top { clip-path: inset(0 calc(100% - var(--pos)) 0 0); }
  .cmp input { position: absolute; left: 0; right: 0; bottom: 8px; width: 100%; }
</style>
<div class="cmp" id="c">
  <img src="edited.webp" alt="Product with the new background">
  <img class="top" src="original.webp" alt="Original product photo">
  <input type="range" min="0" max="100" value="50" aria-label="Compare original and edit">
</div>
<script>
  const c = document.getElementById("c");
  c.querySelector("input").addEventListener("input", e => {
    c.style.setProperty("--pos", e.target.value + "%");
  });
</script>

Why a range input and not drag handlers?

A native range input handles touch, mouse and keyboard, exposes its value to assistive technology and needs no pointer math. The only script is one listener that copies the value into a CSS variable. If you want a visible handle, style the thumb with ::-webkit-slider-thumb and ::-moz-range-thumb.

How do I confirm the edit changed the right thing?

Look at it, then measure it. The masked edit check compares pixels outside the mask so you know the slider is showing the change you asked for and not a shifted background. Host both images yourself; do not point the page at a temporary result URL.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume