Building an Interactive Before-After Slider with JavaScript and React.js | Extraparse

Building an Interactive Before-After Slider with JavaScript and React.js

March 23, 20255 min read981 words

Learn how to create an interactive before-after image slider using HTML, CSS, JavaScript, and React.js.

Table of Contents

Author: Extraparse

Introduction

Creating an interactive before-after slider is a great way to showcase comparisons, such as image transformations, design changes, or project progressions. In this tutorial, we'll walk through building a responsive and interactive before-after slider using HTML, CSS, and JavaScript. Additionally, we'll explore how to implement the same functionality using React.js for more dynamic applications.

HTML Structure

The foundation of our slider consists of a container that holds the before and after images, navigation arrows, and the slider handle itself. Here's the basic HTML structure:

1<div class="container-wrapper">
2 <div class="arrow arrow-left" id="arrow-left">&lt;</div>
3 <div class="slider-container" id="slider-container">
4 <div class="after-image" style="background-image: url('after.png');">
5 <span class="label after">After</span>
6 </div>
7 <div
8 class="before-image"
9 id="before-image"
10 style="background-image: url('before.png');"
11 >
12 <span class="label before">Before</span>
13 </div>
14 <div class="slider" id="slider"></div>
15 </div>
16 <div class="arrow arrow-right" id="arrow-right">&gt;</div>
17</div>

CSS Styling

The CSS is responsible for positioning the images, styling the slider handle, and ensuring responsiveness across different screen sizes. Here's the complete CSS:

1.slider-container {
2 position: relative;
3 height: 500px;
4}
5.slider-container .label {
6 position: absolute;
7 bottom: 10px;
8 font-weight: 300;
9 font-size: 0.75em;
10 pointer-events: none;
11 user-select: none;
12}
13.label.before {
14 left: 10px !important;
15}
16.label.after {
17 right: 10px !important;
18}
19.before-image,
20.after-image {
21 position: absolute;
22 width: 100%;
23 height: 500px;
24 background-size: cover;
25 background-position: center;
26 top: 0;
27 left: 0;
28 display: flex;
29 justify-content: center;
30 align-items: center;
31 color: white;
32 font-size: 24px;
33 font-weight: bold;
34}
35.slider {
36 position: absolute;
37 top: 0;
38 bottom: 0;
39 left: 50%; /* Initial position of the slider */
40 width: 5px;
41 height: 500px;
42 background-color: white; /* Example color */
43 cursor: ew-resize;
44 z-index: 2;
45 transform: translateX(-50%);
46}
47.arrow {
48 width: 30px;
49 height: 30px;
50 display: flex;
51 justify-content: center;
52 align-items: center;
53 cursor: pointer;
54 z-index: 3;
55 user-select: none;
56}
57/* Prevent text/image selection */
58.arrow img {
59 user-select: none;
60 pointer-events: none;
61}
62.arrow.arrow-left {
63 margin-right: 10px;
64}
65.arrow.arrow-right {
66 margin-left: 10px;
67}

JavaScript Functionality

JavaScript adds interactivity to our slider, allowing users to drag the slider handle and click the navigation arrows to adjust the slider position. Here's the complete JavaScript code:

1document.addEventListener("DOMContentLoaded", function () {
2 const sliderContainer = document.getElementById("slider-container");
3 const beforeImage = document.getElementById("before-image");
4 const slider = document.getElementById("slider");
5 const arrowLeft = document.getElementById("arrow-left");
6 const arrowRight = document.getElementById("arrow-right");
7 let isDragging = false;
8 let sliderPosition = 50;
9
10 const updateSlider = (position) => {
11 slider.style.left = `${position}%`;
12 beforeImage.style.clipPath = `inset(0px calc(100% - ${position}%) 0px 0px)`;
13 };
14
15 const handleMouseDown = () => {
16 isDragging = true;
17 };
18 const handleMouseUp = () => {
19 isDragging = false;
20 };
21 const handleMouseMove = (e) => {
22 if (!isDragging) return;
23 const rect = sliderContainer.getBoundingClientRect();
24 let position = ((e.clientX - rect.left) / rect.width) * 100;
25 position = Math.max(2.5, Math.min(position, 97.5));
26 sliderPosition = position;
27 updateSlider(sliderPosition);
28 };
29
30 const handleArrowClick = (direction) => {
31 sliderPosition =
32 direction === "left" ? sliderPosition - 2 : sliderPosition + 2;
33 sliderPosition = Math.max(2.5, Math.min(sliderPosition, 97.5));
34 updateSlider(sliderPosition);
35 };
36
37 slider.addEventListener("mousedown", handleMouseDown);
38 window.addEventListener("mousemove", handleMouseMove);
39 window.addEventListener("mouseup", handleMouseUp);
40 arrowLeft.addEventListener("click", () => handleArrowClick("left"));
41 arrowRight.addEventListener("click", () => handleArrowClick("right"));
42});

React.js Implementation

While the plain JavaScript approach is effective, integrating the slider into a React.js application allows for better state management and reusability. Below is a React component that replicates the functionality of our before-after slider.

1import React, { useState, useRef, useEffect } from "react";
2import "./BeforeAfterSlider.css"; // Ensure you include the CSS styles
3import BeforeImg from "./before.png";
4import AfterImg from "./after.png";
5
6const BeforeAfterSlider = () => {
7 let beforeImage = BeforeImg;
8 let afterImage = AfterImg;
9 const [sliderPosition, setSliderPosition] = useState(50);
10 const containerRef = useRef(null);
11 const isDragging = useRef(false);
12
13 const handleMouseDown = () => {
14 isDragging.current = true;
15 };
16
17 const handleMouseUp = () => {
18 isDragging.current = false;
19 };
20
21 const handleMouseMove = (e) => {
22 if (!isDragging.current) return;
23 const rect = containerRef.current.getBoundingClientRect();
24 let position = e.clientX - rect.left;
25 position = Math.max(2.5, Math.min(position, rect.width - 2.5));
26 setSliderPosition((position / rect.width) * 100);
27 };
28
29 useEffect(() => {
30 window.addEventListener("mousemove", handleMouseMove);
31 window.addEventListener("mouseup", handleMouseUp);
32 return () => {
33 window.removeEventListener("mousemove", handleMouseMove);
34 window.removeEventListener("mouseup", handleMouseUp);
35 };
36 }, []);
37
38 const handleArrowClick = (direction) => {
39 setSliderPosition((prev) => {
40 const newPos = direction === "left" ? prev - 2 : prev + 2;
41 return Math.max(2.5, Math.min(newPos, 97.5));
42 });
43 };
44
45 return (
46 <div className="container-wrapper">
47 <div
48 className="arrow arrow-left"
49 onClick={() => handleArrowClick("left")}
50 >
51 &lt;
52 </div>
53 <div className="slider-container" ref={containerRef}>
54 <div
55 className="after-image"
56 style={{ backgroundImage: `url('${afterImage}')` }}
57 >
58 <span className="label after">After</span>
59 </div>
60 <div
61 className="before-image"
62 style={{
63 backgroundImage: `url('${beforeImage}')`,
64 clipPath: `inset(0px calc(100% - ${sliderPosition}%) 0px 0px)`,
65 }}
66 >
67 <span className="label before">Before</span>
68 </div>
69 <div
70 className="slider"
71 style={{ left: `${sliderPosition}%` }}
72 onMouseDown={handleMouseDown}
73 ></div>
74 </div>
75 <div
76 className="arrow arrow-right"
77 onClick={() => handleArrowClick("right")}
78 >
79 &gt;
80 </div>
81 </div>
82 );
83};
84
85export default BeforeAfterSlider;

Notes:

  • State Management: sliderPosition state controls the position of the slider.
  • Event Handling: Mouse events are managed to handle dragging functionality.
  • Props: beforeImage and afterImage are passed as props for flexibility.
  • Styling: Ensure that the CSS from the earlier section is included for proper styling.

Usage Example:

1import React from "react";
2import BeforeAfterSlider from "./BeforeAfterSlider";
3
4const App = () => {
5 return (
6 <div>
7 <h1>Before-After Slider Example</h1>
8 <BeforeAfterSlider />
9 </div>
10 );
11};
12
13export default App;

Example renderer of the solution

<
After
Before
>

Controlling Slider Behavior

To enhance the slider's functionality and user experience, consider implementing the following:

  • Responsive Adjustments: Ensure the slider adjusts smoothly across various screen sizes using CSS media queries.
  • Touch Support: Enhance mobile usability by adding touch event listeners, allowing users to swipe the slider on touch-enabled devices.
  • Animations: Add CSS transitions to the slider handle and image clips for smoother movements.
  • Accessibility: Incorporate keyboard controls and ARIA labels to make the slider accessible to all users.

Example of Adding CSS Transitions:

1.slider {
2 transition: left 0.3s ease;
3}
4.before-image {
5 transition: clip 0.3s ease;
6}

Conclusion

In this tutorial, we've built a fully functional before-after slider using both plain JavaScript and React.js. This component can be a valuable addition to portfolios, product showcases, and many other applications where visual comparisons are essential. Feel free to customize and extend the slider's functionality to fit your project's needs. Happy coding!

xtelegramfacebooktiktoklinkedin
Author: Extraparse

Comments

You must be logged in to comment.

Loading comments...