Accessible Image Compare — One Line of JavaScript

Mads Stoumann - Jan 19 '21 - - Dev Community

Sometimes it's funny to revisit old ideas and components, you did a long time ago!

I once did an "Image Compare"-component, with one image defined in a regular <img>-tag, one as background-image, a <div> for the draggable control — and a good chunk of JavaScript to handle the functionality.

Looking through old code during a cleanup, I stumbled across this component and thought about what I'd change, if I were to make a "2021 version".

First, I'd replace the <div> with an <input type="range"> for the draggable component. The oninput-event should update a single CSS Custom Property, setting a --value-property on the parentNode, so other children can access the value as well:

Like this:

<input type="range" oninput="this.parentNode.style.setProperty('--value', `${this.value}%`)">
Enter fullscreen mode Exit fullscreen mode

The images should be two regular <img>-tags, and the --value should be used to update two clip-path's:

.c-compare__left {
  clip-path: polygon(0% 0%, var(--value) 0%, var(--value) 100%, 0% 100%);
}
.c-compare__right {
  clip-path: polygon(100% 0%, var(--value) 0%, var(--value) 100%, 100% 100%);
}
Enter fullscreen mode Exit fullscreen mode

And that's the core of it!

A fully functional "Image Compare"-component in one line of JavaScript and two dynamic CSS clip-path: polygon().

The rest is just styling.


Accessibility

You get accessibility for free, since the <input type="range"> is focusable, and navigable with the arrow-keys. Set the :focus-style in CSS.


Demo

Thanks for reading!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .