Create an image comparison slider
Written byPhuoc Nguyen
Category
Level 3 — Advanced
Created
06 Apr, 2020
Last updated
28 Jun, 2021
In this post, we'll create a slider for comparing two images visually. The slider has three elements organized as below:
<div class="container">
<!-- Show the modified image -->
<div class="modified-image"></div>
<!-- The resizer -->
<div class="resizer" id="dragMe"></div>
<!-- The original image -->
<img src="/path/to/original/image.png" />
</div>
#The markup
Initially, the modified image will take half width of the container. It's positioned absolutely to the container:
.container {
position: relative;
}
.modified-image {
/* Absolute position */
left: 0;
position: absolute;
top: 0;
/* Take full height and half width of container */
height: 100%;
width: 50%;
}
We don't use the
`img`
tag to display the modified image here because the image could be scaled. Instead, we use the modified image as the background of modified element:<div class="modified-image" style="background-image: url('/path/to/modified/image.png')"></div>
The modified element uses more styles for showing the background image at desired position:
.modified-image {
background-position: top left;
background-repeat: no-repeat;
background-size: auto 100%;
...;
}
It's a lot easier to set the position for the resizer. It is displayed at the center of container:
.resizer {
/* Absolute position */
left: 50%;
position: absolute;
top: 0;
/* Size */
height: 100%;
width: 2px;
/* Background */
background-color: #cbd5e0;
/* Indicate that it can be resized */
cursor: ew-resize;
}
#Handle the events
When user moves the resizer, we calculate how far the mouse has been moved. Then set the position for the modified and resizer elements based on the current mouse position.
For more information about the idea, you can look at the create resizable split views post.
Here is the piece of code:
// Query the element
const resizer = document.getElementById('dragMe');
const leftSide = resizer.previousElementSibling;
// The current position of mouse
let x = 0;
let y = 0;
// The width of modified element
let leftWidth = 0;
// Handle the mousedown event
// that's triggered when user drags the resizer
const mouseDownHandler = function (e) {
// Get the current mouse position
x = e.clientX;
y = e.clientY;
leftWidth = leftSide.getBoundingClientRect().width;
// Attach the listeners to `document`
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
const mouseMoveHandler = function (e) {
// How far the mouse has been moved
const dx = e.clientX - x;
const dy = e.clientY - y;
let newLeftWidth = ((leftWidth + dx) * 100) / resizer.parentNode.getBoundingClientRect().width;
newLeftWidth = Math.max(newLeftWidth, 0);
newLeftWidth = Math.min(newLeftWidth, 100);
// Set the width for modified and resizer elements
leftSide.style.width = `${newLeftWidth}%`;
resizer.style.left = `${newLeftWidth}%`;
};
// Attach the handler
resizer.addEventListener('mousedown', mouseDownHandler);
When user moves the mouse around, we have to make sure that the mouse isn't moved to out of the container.
That's why we have to compare the
`newLeftWidth`
with 0 and 100 percentages:const mouseMoveHandler = function(e) {
...
newLeftWidth = Math.max(newLeftWidth, 0);
newLeftWidth = Math.min(newLeftWidth, 100);
};
TipThis post uses the Attach event handlers inside other handlers tip
Below is the demo that you can play with.
Photo by frank mckenna on Unsplash
#Demo
#See also
Questions? 🙋
Do you have any questions? Not just about this specific post, but about any topic in front-end development that you'd like to learn more about? If so, feel free to send me a message on Twitter or send me an email. You can find them at the bottom of this page.
I have a long list of upcoming posts, but your questions or ideas for the next one will be my top priority. Let's learn together! Sharing knowledge is the best way to grow 🥷.
Recent posts ⚡
Copy the content of an element to your clipboard
01 Oct, 2023
Make a text area fit its content automatically
30 Sep, 2023
Quickly insert alternate characters while typing
30 Sep, 2023
Zebra-like background
30 Sep, 2023
Add autocomplete to your text area
28 Sep, 2023
Linear scale of a number between two ranges
28 Sep, 2023
Highlight the current line in a text area
27 Sep, 2023
Create your own custom cursor in a text area
27 Sep, 2023
Mirror a text area for improving user experience
26 Sep, 2023
Display the line numbers in a text area
24 Sep, 2023
Select a given line in a text area
24 Sep, 2023
Newsletter 🔔
If you're into front-end technologies and you want to see more of the content I'm creating, then you might want to consider subscribing to my newsletter.
By subscribing, you'll be the first to know about new articles, products, and exclusive promotions.
Don't worry, I won't spam you. And if you ever change your mind, you can unsubscribe at any time.
Phước Nguyễn