This post contains a total of 12+ Hand-Picked JavaScript Comparison Slider Examples with Source Code. All these Comparison Sliders are made using JavaScript and Styled using CSS.
You can use the source code of these examples with credits to the original owner.
Related Posts
JavaScript Comparison Slider Examples
1. By Solygambas
Made by Solygambas. Image Comparison Slider. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: #fef9f2;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
}
.container {
position: relative;
width: 60vw;
height: 80vh;
}
.img-container-before,
.img-container-after {
position: absolute;
width: 60vw;
height: 80vh;
}
.img-container-before {
width: 30vw;
overflow: hidden;
}
img {
width: 60vw;
height: 80vh;
object-fit: cover;
}
.slider {
width: 0.5rem;
background: white;
height: 100%;
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
z-index: 10;
pointer-events: none;
}
</style>
</head>
<body>
<div class="container">
<div class="img-container-after">
<img
src="https://images.unsplash.com/photo-1605405748429-cc26b762fa16?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1336&q=80"
alt=""
class="after"
/>
</div>
<div class="img-container-before">
<img
src="https://images.unsplash.com/photo-1605405747924-2709f6783d0a?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1336&q=80"
alt=""
class="before"
/>
</div>
<div class="slider"></div>
</div>
<script>
const container = document.querySelector(".container");
const slider = document.querySelector(".slider");
const before = document.querySelector(".img-container-before");
const after = document.querySelector(".img-container-after");
const dragSlider = e => {
let x = e.type.includes("mouse") ? e.layerX : e.touches[0].clientX;
let size = container.offsetWidth;
before.style.width = x + "px";
slider.style.left = x + "px";
if (x < 30) {
before.style.width = 0;
slider.style.left = 0;
}
if (x + 30 > size) {
before.style.width = size + "px";
slider.style.left = size + "px";
}
};
// Mouse event
container.addEventListener("mousemove", dragSlider);
// Touch and drag events
container.addEventListener("touchstart", dragSlider);
container.addEventListener("touchmove", dragSlider);
</script>
</body>
</html>
2. By PBM
Made by PBM. Car Image Slider. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<style>
body{
background-color: #eee;
}
div{
width: 600px;
height: 400px;
background: url(https://koenromers.com/cocoen/after.jpg);
background-size: cover;
position: relative;
margin:30px auto;
z-index:1;
}
div:after{
content:'';
position: absolute;
width:0;
height:0;
border: 10px solid transparent;
border-right: 10px solid white;
left: 42%;
top:50%;
transform: translate(-50%, -50%);
animation: left 1s 2 forwards alternate;
opacity: .7;
}
div:before{
content:'';
position: absolute;
width:0;
height:0;
border: 10px solid transparent;
border-left: 10px solid white;
left:58%;
top:50%;
transform: translate(-50%, -50%);
z-index:10;
animation: right 1s 2 forwards alternate;
opacity: .7;
}
figure{
position: absolute;
background: url(https://koenromers.com/cocoen/before.jpg);
background-size:cover;
width: 50%;
height:100%;
margin:0;
z-index: -1;
}
input[type=range]{
-webkit-appearance: none;
postion: absolute;
width:100%;
height:100%;
background: black;
opacity: .7;
outline:none;
margin:auto;
padding:0;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 100%;
width: 10px;
background: white;
position: relative;
border:none;
cursor: pointer;
outline: 5px solid transparent;
opacity:.7;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 400px;
background: transparent;
}
input[type=range]::-moz-range-thumb {
height: 100%;
width: 10px;
background-color: white;
position: relative;
border:none;
cursor: pointer;
border-radius: 0;
opacity:.7;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 400px;
background: transparent;
}
input[type=range]::-ms-thumb {
height: 400px;
width: 10px;
background: white;
position: relative;
border:none;
border-radius: 0;
opacity:.7;
}
input[type=range]:focus::-ms-thumb {
border: none;
}
input[type=range]::-ms-track {
width: 100%;
height: 400px;
cursor: pointer;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower, input[type=range]::-ms-fill-upper {
background: transparent;
}
input[type=range]::-ms-tooltip{
display:none;
}
@keyframes left{
to{
left: 40%;
}
}
@keyframes right{
to{
left: 60%;
}
}
@media(max-width: 620px){
div{
width:90%;
height: 300px;
}
input[type=range]::-webkit-slider-runnable-track {
height: 300px;
}
input[type=range]::-moz-range-track{
height:300px;
}
input[type=range]::-ms-track{
height:300px;
}
input[type=range]::-ms-thumb{
height:300px;
}
}
</style>
</head>
<body>
<div>
<figure>
</figure>
<input type="range" min=0 max=100 value=50/>
</div>
<script>
document.querySelector("figure").style.width = this.value + "%";
setTimeout(hideTutorialElements, 1000);
document.querySelector("input").oninput = function () {
compare(this);
};
//for IE
document.querySelector("input").onchange = function () {
compare(this);
};
function compare(element) {
if (element.value > 98) element.value = 98;else
if (element.value < 2) element.value = 2;
document.querySelector("figure").style.width = element.value + "%";
}
function hideTutorialElements() {
document.querySelector("input[type=range]").style.background = "transparent";
document.querySelector("input[type=range]").style.opacity = 1;
//CSS pseudo-elements
document.styleSheets[0].
insertRule('div:after {display: none; }', 1);
document.styleSheets[0].
insertRule('div:before {display: none; }', 1);
}
</script>
</body>
</html>
3. By Kocsten
Made by Kocsten. Before / After Image Comparison Slider. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js" type="text/javascript"></script>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<style>
*, *:after, *:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
font-size: 100%;
font-family: "Open Sans", sans-serif;
color: #445b7c;
background-color: #445b7c;
}
a {
color: #dc717d;
text-decoration: none;
}
img {
max-width: 100%;
}
header {
position: relative;
height: 160px;
line-height: 160px;
text-align: center;
}
header h1 {
font-size: 22px;
font-size: 1.375rem;
color: #ffffff;
font-weight: 300;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@media only screen and (min-width: 768px) {
header {
height: 240px;
line-height: 240px;
}
header h1 {
font-size: 32px;
font-size: 2rem;
}
}
.image-container {
position: relative;
width: 90%;
max-width: 768px;
margin: 2em auto;
}
.image-container img {
display: block;
}
@media only screen and (min-width: 768px) {
.image-container {
margin: 4em auto;
}
}
.image-label {
position: absolute;
bottom: 0;
right: 0;
color: #ffffff;
padding: 1em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
opacity: 0;
-webkit-transform: translateY(20px);
-moz-transform: translateY(20px);
-ms-transform: translateY(20px);
-o-transform: translateY(20px);
transform: translateY(20px);
-webkit-transition: -webkit-transform 0.3s 0.7s, opacity 0.3s 0.7s;
-moz-transition: -moz-transform 0.3s 0.7s, opacity 0.3s 0.7s;
transition: transform 0.3s 0.7s, opacity 0.3s 0.7s;
}
.image-label.is-hidden {
visibility: hidden;
}
.is-visible .image-label {
opacity: 1;
-webkit-transform: translateY(0);
-moz-transform: translateY(0);
-ms-transform: translateY(0);
-o-transform: translateY(0);
transform: translateY(0);
}
.resize-image {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 100%;
overflow: hidden;
background: url("https://webdevtrick.com/wp-content/uploads/skynaturemod.jpg") no-repeat left top;
background-size: auto 100%;
-webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.resize-image .image-label {
right: auto;
left: 0;
}
.is-visible .resize-image {
width: 50%;
-webkit-animation: cd-bounce-in 0.7s;
-moz-animation: cd-bounce-in 0.7s;
animation: cd-bounce-in 0.7s;
}
@-webkit-keyframes cd-bounce-in {
0% {
width: 0;
}
60% {
width: 55%;
}
100% {
width: 50%;
}
}
@-moz-keyframes cd-bounce-in {
0% {
width: 0;
}
60% {
width: 55%;
}
100% {
width: 50%;
}
}
@keyframes cd-bounce-in {
0% {
width: 0;
}
60% {
width: 55%;
}
100% {
width: 50%;
}
}
.handle {
position: absolute;
height: 44px;
width: 44px;
left: 50%;
top: 50%;
margin-left: -22px;
margin-top: -22px;
border-radius: 50%;
background: #dc717d url("https://webdevtrick.com/wp-content/uploads/arrows.svg") no-repeat center center;
cursor: move;
box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.2), 0 0 10px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.3);
opacity: 0;
-webkit-transform: translate3d(0, 0, 0) scale(0);
-moz-transform: translate3d(0, 0, 0) scale(0);
-ms-transform: translate3d(0, 0, 0) scale(0);
-o-transform: translate3d(0, 0, 0) scale(0);
transform: translate3d(0, 0, 0) scale(0);
}
.handle.draggable {
background-color: #445b7c;
}
.is-visible .handle {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) scale(1);
-moz-transform: translate3d(0, 0, 0) scale(1);
-ms-transform: translate3d(0, 0, 0) scale(1);
-o-transform: translate3d(0, 0, 0) scale(1);
transform: translate3d(0, 0, 0) scale(1);
-webkit-transition: -webkit-transform 0.3s 0.7s, opacity 0s 0.7s;
-moz-transition: -moz-transform 0.3s 0.7s, opacity 0s 0.7s;
transition: transform 0.3s 0.7s, opacity 0s 0.7s;
}
.codes{
bottom: 5%;
left: 5%;
position: fixed;
}
.codes div {
border: 2px solid black;
font-size: 20px;
padding: 10px;
background-color: red;
}
.codes div a{
text-decoration: none;
color: white;
font-weight: 800;
}
</style>
</head>
<body>
<figure class="image-container">
<img src="https://webdevtrick.com/wp-content/uploads/skynature.jpg" alt="Original Image">
<span class="image-label" data-type="original">Original</span>
<div class="resize-image">
<span class="image-label" data-type="modified">Modified</span>
</div>
<span class="handle"></span>
</figure>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script>
jQuery(document).ready(function ($) {
//check if the .image-container is in the viewport
//if yes, animate it
checkPosition($('.image-container'));
$(window).on('scroll', function () {
checkPosition($('.image-container'));
});
//make the .handle element draggable and modify .resize-image width according to its position
drags($('.handle'), $('.resize-image'), $('.image-container'), $('.image-label[data-type="original"]'), $('.image-label[data-type="modified"]'));
//upadate images label visibility
$(window).on('resize', function () {
updateLabel($('.image-label[data-type="modified"]'), $('.resize-image'), 'left');
updateLabel($('.image-label[data-type="original"]'), $('.resize-image'), 'right');
});
});
function checkPosition(container) {
if ($(window).scrollTop() + $(window).height() * 0.5 > container.offset().top) {
container.addClass('is-visible');
//you can uncomment the following line if you don't have other events to bind to the window scroll
// $(window).off('scroll');
}
}
//draggable funtionality
function drags(dragElement, resizeElement, container, labelContainer, labelResizeElement) {
dragElement.on("mousedown vmousedown", function (e) {
dragElement.addClass('draggable');
resizeElement.addClass('resizable');
var dragWidth = dragElement.outerWidth(),
xPosition = dragElement.offset().left + dragWidth - e.pageX,
containerOffset = container.offset().left,
containerWidth = container.outerWidth(),
minLeft = containerOffset + 10,
maxLeft = containerOffset + containerWidth - dragWidth - 10;
dragElement.parents().on("mousemove vmousemove", function (e) {
leftValue = e.pageX + xPosition - dragWidth;
//constrain the draggable element to move inside his container
if (leftValue < minLeft) {
leftValue = minLeft;
} else if (leftValue > maxLeft) {
leftValue = maxLeft;
}
widthValue = (leftValue + dragWidth / 2 - containerOffset) * 100 / containerWidth + '%';
$('.draggable').css('left', widthValue).on("mouseup vmouseup", function () {
$(this).removeClass('draggable');
resizeElement.removeClass('resizable');
});
$('.resizable').css('width', widthValue);
updateLabel(labelResizeElement, resizeElement, 'left');
updateLabel(labelContainer, resizeElement, 'right');
}).on("mouseup vmouseup", function (e) {
dragElement.removeClass('draggable');
resizeElement.removeClass('resizable');
});
e.preventDefault();
}).on("mouseup vmouseup", function (e) {
dragElement.removeClass('draggable');
resizeElement.removeClass('resizable');
});
}
function updateLabel(label, resizeElement, position) {
if (position == 'left') {
label.offset().left + label.outerWidth() < resizeElement.offset().left + resizeElement.outerWidth() ? label.removeClass('is-hidden') : label.addClass('is-hidden');
} else {
label.offset().left > resizeElement.offset().left + resizeElement.outerWidth() ? label.removeClass('is-hidden') : label.addClass('is-hidden');
}
}
</script>
</body>
</html>
4. By FrankyJo
Made by FrankyJo. Image Comparison Slider with Grayscale Effect. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
body {
display: flex;
align-items: center;
justify-content: center;
background: #333333;
height: 100vh;
}
.compare {
position: relative;
height: 400px;
width: 700px;
overflow: hidden;
}
.compare__delimeter {
position: absolute;
top: 0px;
width: 3px;
height: 100%;
background: #333333;
cursor: grab;
z-index: 2;
}
.compare__delimeter:before, .compare__delimeter:after {
content: '';
display: block;
position: absolute;
top: 50%;
width: 20px;
height: 40px;
background: #222222;
border: 1px solid #f2f2f2;
transform: translate(0, -50%);
}
.compare__delimeter:before {
left: 5px;
border-radius: 3px 20px 20px 3px;
}
.compare__delimeter:after {
right: 5px;
border-radius: 20px 3px 3px 20px;
}
.compare__image {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
border-radius: 5px;
}
.compare__image img {
width: 700px;
height: 400px;
object-fit: cover;
}
.compare__after {
filter: grayscale(1);
}
</style>
</head>
<body>
<div class="compare">
<div class="compare__image">
<img src="https://wallpaperaccess.com/full/1131217.jpg" alt="">
</div>
<div class="compare__delimeter"></div>
<div class="compare__image compare__after" >
<img src="https://wallpaperaccess.com/full/1131217.jpg" alt="">
</div>
</div>
<script>
const imageAfter = document.querySelector('.compare__after');
const widthImageAfter = imageAfter.offsetWidth;
const heightImageAfter = imageAfter.offsetHeight;
const delimeter = document.querySelector('.compare__delimeter');
let isActive = false;
compare();
function compare() {
delimeter.style.left = widthImageAfter / 2 - delimeter.offsetWidth / 2 + 'px';
imageAfter.style.width = '50%';
setListeners();
}
function setListeners() {
delimeter.addEventListener('mousedown', activeDelimeter);
delimeter.addEventListener('touchstart', activeDelimeter);
window.addEventListener('mousemove', onMoveDelimeter);
window.addEventListener('touchmove', onMoveDelimeter);
window.addEventListener('mouseup', () => {
isActive = false;
});
window.addEventListener('touchstop', () => {
isActive = false;
});
}
function activeDelimeter(event) {
event.preventDefault();
isActive = true;
}
function onMoveDelimeter(event) {
if (!isActive) return;
moveSlide(currentPositionDelimeter(event));
}
function currentPositionDelimeter(event) {
let image = imageAfter.getBoundingClientRect();
let x = 0;
x = event.pageX - image.left;
if (x < 0) {
x = 0;
}
if (x > widthImageAfter) {
x = widthImageAfter;
}
return x;
}
function moveSlide(x) {
imageAfter.style.width = x + 'px';
delimeter.style.left = imageAfter.offsetWidth - delimeter.offsetWidth / 2 + 'px';
}
</script>
</body>
</html>
5. By Cam
Made by Cam. JavaScript Image Comparison slider with automatic cursor follower. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<style>
body {
background: radial-gradient(at 70% top, #fff 0%, #e0e0e0 100%);
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
width: 100%;
}
.Image-Compare {
--width: 794px;
--height: 446px;
position: relative;
width: var(--width);
height: var(--height);
overflow: hidden;
}
.Image-Compare__image {
position: absolute;
height: 100%;
background: url("https://images.unsplash.com/photo-1498248193836-88f8c8d70a3f?w=2382&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D");
background-size: var(--width) var(--height);
}
.Image-Compare__image:first-child {
left: 0;
width: 100%;
background-position: center left;
}
.Image-Compare__image:last-child {
right: 0;
width: calc(100% - var(--x, 50%));
background-position: center right;
filter: grayscale(100%);
box-shadow: inset 2px 0 0 #111, -2px 0 0 #111;
}
</style>
</head>
<body>
<div class="Contain">
<div class="Image-Compare">
<div class="Image-Compare__image"></div>
<div class="Image-Compare__image"></div>
</div>
</div>
<script>
document.querySelectorAll('.Image-Compare').forEach(function (elem) {
var x = undefined,
width = undefined;
elem.onmouseenter = function () {
var size = elem.getBoundingClientRect();
x = size.x;
width = size.width;
};
elem.onmousemove = function (e) {
var horizontal = (e.clientX - x) / width * 100;
elem.style.setProperty('--x', horizontal + '%');
};
});
</script>
</body>
</html>
6. By Arthur
Made by Arthur. Before / After Comparison slider with range button. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Oswald&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<style>
@charset "UTF-8";
/* ___ variables ___ */
/*
__ mixins.scss __
*/
/* ___ global.scss */
*,
*::before,
*::after {
box-sizing: inherit;
}
body {
min-height: 100vh;
display: grid;
place-items: center;
box-sizing: border-box;
font-family: "Oswald", "Arial", "Helvetica", sans-serif;
background-color: #eaeaea;
text-transform: uppercase;
grid-template-columns: min(100%, 300px);
place-content: center;
padding-left: 20px;
padding-right: 20px;
}
@media (min-width: 600px) {
body {
--back-divide: 50%;
background-image: linear-gradient(to right, transparent var(--back-divide), #dddddd var(--back-divide));
}
}
/*
__ visually-hidden.scss __
Доступное скрытие
*/
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
border: 0;
clip: rect(0 0 0 0);
}
/* __ switcher.scss __ */
.switcher {
border: none;
padding: 0;
margin: 0;
position: relative;
display: grid;
grid-template-columns: -webkit-min-content 1fr -webkit-min-content;
grid-template-columns: min-content 1fr min-content;
align-items: center;
gap: 18px;
}
.switcher[hidden] {
display: none;
}
.switcher__wrapper {
background-color: #fff;
display: inline-flex;
border: 1px solid #cdcdcd;
border-radius: 6px;
min-width: 40px;
height: 14px;
cursor: pointer;
position: relative;
}
.switcher__wrapper:hover, .switcher__wrapper:focus-within {
border-color: #ff91ab;
background-color: #f2f2f2;
}
.switcher__radio {
display: inline-block;
margin-right: -2px;
width: 50%;
height: 100%;
opacity: 0;
position: relative;
z-index: 1;
cursor: pointer;
}
.switcher__thumb {
height: 42.86%;
width: calc(50% - 6px);
display: block;
background-color: #ff91ab;
border-radius: 6px;
transition: transform 0.1s ease-out;
z-index: 2;
position: absolute;
left: 6px;
top: 28.57%;
pointer-events: none;
}
.switcher__radio--on:checked ~ .switcher__thumb {
transform: translateX(100%);
}
.comparison__slides {
margin: 0 0 20px;
padding: 0;
list-style: none;
overflow-x: auto;
display: flex;
-ms-scroll-snap-type: x mandatory;
scroll-snap-type: x mandatory;
scrollbar-color: transparent transparent;
/* thumb and track color */
scrollbar-width: 0px;
-ms-overflow-style: none;
}
.comparison__slides::-webkit-scrollbar {
width: 0;
height: 0;
}
.comparison__slides::-webkit-scrollbar-track {
background: transparent;
}
.comparison__slides::-webkit-scrollbar-thumb {
background: transparent;
border: none;
}
.comparison__slide {
flex: 0 0 100%;
display: block;
scroll-snap-align: start;
}
.comparison__image {
width: 100%;
height: auto;
}
.comparison__controls {
display: grid;
gap: 12px;
}
.comparison__range-wrapper {
display: grid;
gap: 22px;
grid-auto-flow: column;
align-items: center;
padding: 0;
margin: 0;
border: none;
}
.comparison__range-wrapper--activated {
grid-template-columns: -webkit-min-content 1fr -webkit-min-content;
grid-template-columns: min-content 1fr min-content;
display: none;
}
.comparison__control {
color: inherit;
font-size: 16px;
line-height: 1.25;
text-transform: uppercase;
color: #000000;
}
.comparison__control[href] {
-webkit-text-decoration: underline dotted rgba(0, 0, 0, 0.24);
text-decoration: underline dotted rgba(0, 0, 0, 0.24);
text-underline-offset: 0.2em;
}
.comparison__control--right {
text-align: right;
}
@media (min-width: 600px) {
.comparison__range-wrapper--activated {
display: grid;
}
.comparison__switcher {
display: none;
}
.comparison__slides {
position: relative;
width: 100%;
--slider-divide: 50%;
}
.comparison__slide {
-webkit-clip-path: polygon(0 0, var(--slider-divide) 0, var(--slider-divide) 100%, 0 100%);
clip-path: polygon(0 0, var(--slider-divide) 0, var(--slider-divide) 100%, 0 100%);
}
.comparison__slide:last-child {
position: absolute;
width: 100%;
height: 100%;
-webkit-clip-path: polygon(var(--slider-divide) 0, 100% 0, 100% 100%, var(--slider-divide) 100%);
clip-path: polygon(var(--slider-divide) 0, 100% 0, 100% 100%, var(--slider-divide) 100%);
}
}
.custom-range[type=range] {
width: 100%;
margin: 15px 0;
background-color: transparent;
-webkit-appearance: none;
}
.custom-range[type=range]:focus {
outline: none;
}
.custom-range[type=range]:hover::-webkit-slider-thumb {
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2), inset 0px 0 0px 10px white;
}
.custom-range[type=range]:focus::-webkit-slider-thumb, .custom-range[type=range]:active::-webkit-slider-thumb {
box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.2), inset 0px 0 0px 10px white;
border-color: #ff91ab;
}
.custom-range[type=range]::-webkit-slider-runnable-track {
background-color: #c4c4c4;
border-radius: 6px;
width: 100%;
height: 6px;
cursor: pointer;
}
.custom-range[type=range]::-moz-range-track {
background-color: #c4c4c4;
border-radius: 6px;
width: 100%;
height: 6px;
cursor: pointer;
}
.custom-range[type=range]::-webkit-slider-thumb {
margin-top: -12px;
width: 30px;
height: 30px;
background-color: #ff91ab;
border: 1px solid #cdcdcd;
border-radius: 50%;
cursor: pointer;
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.16), inset 0px 0 0px 10px white;
-webkit-appearance: none;
}
.custom-range[type=range]::-moz-range-thumb {
width: 30px;
height: 30px;
background-color: #ff91ab;
border: 1px solid #cdcdcd;
border-radius: 50%;
cursor: pointer;
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.16), inset 0px 0 0px 10px white;
}
</style>
</head>
<body>
<article class="comparison">
<ul class="comparison__slides">
<li class="comparison__slide" id="before"><img class="comparison__image" src="https://svgur.com/i/WRr.svg" width="224" height="224" alt="Kitty wants coffee"/></li>
<li class="comparison__slide" id="after"><img class="comparison__image" src="https://svgur.com/i/WQf.svg" width="224" height="224" alt="Kitty is ready"/></li>
</ul>
<form class="comparison__controls">
<fieldset class="comparison__range-wrapper">
<legend class="visually-hidden">Choose which picture to show</legend><a class="comparison__control" href="#before">Before</a>
<input class="comparison__range custom-range" type="range" min="0" max="100" value="50" hidden="hidden"/><a class="comparison__control comparison__control--right" href="#after">After</a>
</fieldset>
<fieldset class="switcher comparison__switcher" role="radiogroup" hidden="hidden">
<legend class="visually-hidden">Comparison switcher</legend>
<label class="comparison__control" for="before-radio">Before</label>
<div class="switcher__wrapper">
<input class="switcher__radio" id="before-radio" type="radio" name="comparison-switcher" checked="checked"/>
<input class="switcher__radio switcher__radio--on" id="after-radio" type="radio" name="comparison-switcher"/><span class="switcher__thumb" aria-hidden="true"></span>
</div>
<label class="comparison__control" for="after-radio">After</label>
</fieldset>
</form>
</article>
<script>
/* switcher.js */
const switcher = document.querySelector(".switcher");
const switcherWrapper = switcher.querySelector(".switcher__wrapper");
const switcherRadios = switcherWrapper.querySelectorAll(".switcher__radio");
switcherWrapper.addEventListener("focusin", evt => {
switcherWrapper.addEventListener("keydown", evt => {
if (event.key === "Enter" || event.key === " ") {
evt.preventDefault();
toogleSwitch();
}
});
});
function toogleSwitch() {
if (switcherRadios[0].checked) {
switcherRadios[1].checked = true;
} else {
switcherRadios[0].checked = true;
}
}
/* comparison.js */
const compasion = document.querySelector(".comparison");
const compasionWrapper = compasion.querySelector(".comparison__slides");
const WIDTH = compasionWrapper.offsetWidth;
const compasionSlides = compasionWrapper.querySelectorAll(".comparison__slide");
const compasionRange = compasion.querySelector(".comparison__range");
const compasionSwitcher = compasion.querySelector(".comparison__switcher");
const compasionRadios = compasionSwitcher.querySelectorAll(".switcher__radio");
const compasionControls = compasion.querySelectorAll("a.comparison__control");
compasionSwitcher.hidden = false;
compasionRange.hidden = false;
compasionRange.parentElement.classList.add(
`${compasionRange.parentElement.classList[0]}--activated`);
compasionSwitcher.addEventListener("change", evt => {
const scrollPosition = evt.target.id.includes("after") ? WIDTH : 0;
compasionWrapper.scrollTo({
left: scrollPosition,
behavior: "smooth" });
});
compasionRange.addEventListener("input", updateSlider);
compasionControls.forEach((control, index) => {
control.addEventListener("click", evt => {
evt.preventDefault();
compasionRange.value =
index === 0 ? compasionRange.min : compasionRange.max;
updateSlider();
});
});
function updateSlider() {
const inverseValue = compasionRange.max - compasionRange.value;
compasionWrapper.style.setProperty("--slider-divide", inverseValue + "%");
const parentWidth = compasion.parentNode.offsetWidth;
let backgroundDividePoint =
compasionWrapper.offsetLeft + WIDTH * inverseValue / compasionRange.max;
updateBackround(backgroundDividePoint + "px");
if (compasionRange.value === compasionRange.max) {
updateBackround(0);
}
if (compasionRange.value === compasionRange.min) {
updateBackround("100%");
}
}
function updateBackround(value) {
compasion.parentNode.style.setProperty("--back-divide", value);
}
</script>
</body>
</html>
7. By Ivan Markovic
Made by Ivan Markovic. Responsive image comparison slider. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.container {
position: relative;
width: 100%;
height: 100vh;
background-image: url(https://raw.githubusercontent.com/ivanmmarkovic/misc/master/images/large/aerial-shot-bird-s-eye-view-forest-1660004.jpg);
background-position: center center;
background-size: cover;
overflow: hidden;
}
.mask-container {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 50%;
overflow: hidden;
}
.mask-image-container {
position: absolute;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
background-image: url(https://raw.githubusercontent.com/ivanmmarkovic/misc/master/images/large/aerial-view-color-daylight-1125278.jpg);
background-position: center center;
background-size: cover;
}
.border {
position: absolute;
width: 4px;
height: 100vh;
left: 50%;
margin-left: -2px;
background-color: rgba(0,0,0,0.4);
}
.circle {
position: absolute;
width: 50px;
height: 50px;
border-radius: 50%;
background-color: steelblue;
top: 50%;
margin-top: -25px;
left: 50%;
margin-left: -25px;
opacity: 0.9;
cursor: ew-resize;
}
</style>
</head>
<body>
<div class="container">
<div class="mask-container">
<div class="mask-image-container">
</div>
</div>
<div class="border"></div>
<div class="circle"></div>
</div>
<script>
let container = document.querySelector(".container");
let maskContainer = document.querySelector(".mask-container");
let maskImageContainer = document.querySelector(".mask-image-container");
let border = document.querySelector(".border");
let circle = document.querySelector(".circle");
circle.style.draggable = true;
circle.ondrag = function (event) {
maskContainer.style.width = event.pageX + "px";
border.style.left = event.pageX + "px";
circle.style.left = event.pageX + "px";
};
circle.ondragend = function (event) {
maskContainer.style.width = event.pageX + "px";
border.style.left = event.pageX + "px";
circle.style.left = event.pageX + "px";
};
</script>
</body>
</html>
8. By boomclap
Made by boomclap. Basic JavaScript Photo Comparison Slider. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css'>
<style>
.cd-image-container {
position: relative;
width: 90%;
max-width: 1080px;
margin: 0em auto;
}
.cd-image-container img {
display: block;
}
.cd-image-label {
position: absolute;
bottom: 0;
right: 55px;
color: #000000;
padding: 1em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
opacity: 0;
-webkit-transform: translateY(20px);
-moz-transform: translateY(20px);
-ms-transform: translateY(20px);
-o-transform: translateY(20px);
transform: translateY(20px);
-webkit-transition: -webkit-transform 0.3s 0.7s, opacity 0.3s 0.7s;
-moz-transition: -moz-transform 0.3s 0.7s, opacity 0.3s 0.7s;
transition: transform 0.3s 0.7s, opacity 0.3s 0.7s;
}
.cd-image-label.is-hidden {
visibility: hidden;
}
.is-visible .cd-image-label {
opacity: 1;
-webkit-transform: translateY(0);
-moz-transform: translateY(0);
-ms-transform: translateY(0);
-o-transform: translateY(0);
transform: translateY(0);
}
.cd-resize-img {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 100%;
overflow: hidden;
/* Force Hardware Acceleration in WebKit */
-webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.cd-resize-img img {
position: absolute;
left: 0;
top: 0;
display: block;
height: 100%;
width: auto;
max-width: none;
}
.cd-resize-img .cd-image-label {
right: auto;
left: 0;
}
.is-visible .cd-resize-img {
width: 50%;
/* bounce in animation of the modified image */
-webkit-animation: cd-bounce-in 0.7s;
-moz-animation: cd-bounce-in 0.7s;
animation: cd-bounce-in 0.7s;
}
@-webkit-keyframes cd-bounce-in {
0% {
width: 0;
}
60% {
width: 55%;
}
100% {
width: 50%;
}
}
@-moz-keyframes cd-bounce-in {
0% {
width: 0;
}
60% {
width: 55%;
}
100% {
width: 50%;
}
}
@keyframes cd-bounce-in {
0% {
width: 0;
}
60% {
width: 55%;
}
100% {
width: 50%;
}
}
.cd-handle {
position: absolute;
height: 44px;
width: 44px;
/* center the element */
left: 50%;
top: 50%;
margin-left: -22px;
margin-top: -22px;
border-radius: 50%;
background: #dc717d url("https://codyhouse.co/demo/image-comparison-slider/img/cd-arrows.svg") no-repeat center center;
cursor: move;
box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.2), 0 0 10px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.3);
opacity: 0;
-webkit-transform: translate3d(0, 0, 0) scale(0);
-moz-transform: translate3d(0, 0, 0) scale(0);
-ms-transform: translate3d(0, 0, 0) scale(0);
-o-transform: translate3d(0, 0, 0) scale(0);
transform: translate3d(0, 0, 0) scale(0);
}
.cd-handle.draggable {
/* change background color when element is active */
background-color: #445b7c;
}
.is-visible .cd-handle {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) scale(1);
-moz-transform: translate3d(0, 0, 0) scale(1);
-ms-transform: translate3d(0, 0, 0) scale(1);
-o-transform: translate3d(0, 0, 0) scale(1);
transform: translate3d(0, 0, 0) scale(1);
-webkit-transition: -webkit-transform 0.3s 0.7s, opacity 0s 0.7s;
-moz-transition: -moz-transform 0.3s 0.7s, opacity 0s 0.7s;
transition: transform 0.3s 0.7s, opacity 0s 0.7s;
}
</style>
</head>
<body>
<figure class="cd-image-container">
<img src="http://gearnuke.com/wp-content/uploads/2015/04/gtav-ps4-comp-3-1024x576.jpg" style="max-width: 100%;"alt="Original Image" >
<span class="cd-image-label" data-type="original">Text</span>
<div class="cd-resize-img slide-img" > <!-- the resizable image on top -->
<img src="http://gearnuke.com/wp-content/uploads/2015/04/gtav-pc-normal-9-1024x576.jpg" alt="Modified Image" >
<span class="cd-image-label" data-type="modified">Text</span>
</div>
<span class="cd-handle"></span>
</figure> <!-- cd-image-container -->
<script src='https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.js'></script>
<script src='https://code.jquery.com/jquery-2.1.1.js'></script>
<script>
jQuery(document).ready(function ($) {
//check if the .cd-image-container is in the viewport
//if yes, animate it
checkPosition($('.cd-image-container'));
$(window).on('scroll', function () {
checkPosition($('.cd-image-container'));
});
//make the .cd-handle element draggable and modify .cd-resize-img width according to its position
$('.cd-image-container').each(function () {
var actual = $(this);
drags(actual.find('.cd-handle'), actual.find('.cd-resize-img'), actual, actual.find('.cd-image-label[data-type="original"]'), actual.find('.cd-image-label[data-type="modified"]'));
});
//upadate images label visibility
$(window).on('resize', function () {
$('.cd-image-container').each(function () {
var actual = $(this);
updateLabel(actual.find('.cd-image-label[data-type="modified"]'), actual.find('.cd-resize-img'), 'left');
updateLabel(actual.find('.cd-image-label[data-type="original"]'), actual.find('.cd-resize-img'), 'right');
});
});
});
function checkPosition(container) {
container.each(function () {
var actualContainer = $(this);
if ($(window).scrollTop() + $(window).height() * 0.5 > actualContainer.offset().top) {
actualContainer.addClass('is-visible');
}
});
}
//draggable funtionality - credits to https://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/
function drags(dragElement, resizeElement, container, labelContainer, labelResizeElement) {
dragElement.on("mousedown vmousedown", function (e) {
dragElement.addClass('draggable');
resizeElement.addClass('resizable');
var dragWidth = dragElement.outerWidth(),
xPosition = dragElement.offset().left + dragWidth - e.pageX,
containerOffset = container.offset().left,
containerWidth = container.outerWidth(),
minLeft = containerOffset + 10,
maxLeft = containerOffset + containerWidth - dragWidth - 10;
dragElement.parents().on("mousemove vmousemove", function (e) {
leftValue = e.pageX + xPosition - dragWidth;
//constrain the draggable element to move inside his container
if (leftValue < minLeft) {
leftValue = minLeft;
} else if (leftValue > maxLeft) {
leftValue = maxLeft;
}
widthValue = (leftValue + dragWidth / 2 - containerOffset) * 95 / containerWidth + '%';
$('.draggable').css('left', widthValue).on("mouseup vmouseup", function () {
$(this).removeClass('draggable');
resizeElement.removeClass('resizable');
});
$('.resizable').css('width', widthValue);
updateLabel(labelResizeElement, resizeElement, 'left');
updateLabel(labelContainer, resizeElement, 'right');
}).on("mouseup vmouseup", function (e) {
dragElement.removeClass('draggable');
resizeElement.removeClass('resizable');
});
e.preventDefault();
}).on("mouseup vmouseup", function (e) {
dragElement.removeClass('draggable');
resizeElement.removeClass('resizable');
});
}
function updateLabel(label, resizeElement, position) {
if (position == 'left') {
label.offset().left + label.outerWidth() < resizeElement.offset().left + resizeElement.outerWidth() ? label.removeClass('is-hidden') : label.addClass('is-hidden');
} else {
label.offset().left > resizeElement.offset().left + resizeElement.outerWidth() ? label.removeClass('is-hidden') : label.addClass('is-hidden');
}
}
</script>
</body>
</html>
9. By Nahid
Made by Nahid. Image Comparison Slider with Grayscale effect. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<style>
* {
padding: 0;
margin: 0;
/* box-sizing: border-box; */
/* cursor: none !important; */
font-family: 'Poppins', sans-serif;
}
section {
position: absolute;
width: 100%;
height: 100vh;
overflow: hidden;
background: url(https://images.hdqwalls.com/wallpapers/urban-cityscape-artwork-cq.jpg);
background-position: center;
background-size: cover;
background-attachment: fixed;
}
#layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background: url(https://images.hdqwalls.com/wallpapers/urban-cityscape-artwork-cq.jpg);
background-position: center;
background-size: cover;
filter: grayscale(100%);
background-attachment: fixed;
border-left: 5px solid #fff;
}
</style>
</head>
<body>
<section>
<div id="layer"></div>
</section>
<script>
var slide = document.getElementById("layer");
window.onmousemove = function (e) {
var x = e.clientX;
slide.style.left = x + "px";
// var y = e.clientY
};
</script>
</body>
</html>
10. By Qrolic Technologies
Made by Qrolic Technologies. Image before & after comparison slider using JQuery. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/foundation/5.5.0/css/foundation.css'>
<link rel='stylesheet' href='https://s3-us-west-2.amazonaws.com/s.cdpn.io/124874/twentytwenty.css'>
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:[email protected];200;300;400;500;600;700;800&display=swap');
body{
font-family: 'Poppins', sans-serif;
background-color: #EDF2F4;
}
.container{
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.box__inner{
width: 600px;
}
.title span{
color: #EF233C;
}
.title{
padding-bottom: 50px;
text-align: center;
}
p{
color: #2B2D42;
font-size: 20px;
line-height: 25px;
}
a{
color: #EF233C;
}
a:hover{
color: #8D99AE;
}
h1 {
text-align: center;
font-size: 35px;
line-height: 40px;
color: #2B2D42;
font-weight: 600;
font-family: 'Poppins', sans-serif;
}
</style>
</head>
<body>
<section>
<div class="container">
<div class="content">
<div class="title">
<div class="box">
<div class="box__inner">
<div id="before_after">
<img src="https://i.ibb.co/F8rDyhv/before.jpg">
<img src="https://i.ibb.co/0shfDNN/after.jpg">
</div>
</div>
</div>
</div>
</div>
</section>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/124874/jquery.event.move.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/124874/jquery.twentytwenty.js'></script>
<script>
$(window).load(function () {
$("#before_after").twentytwenty();
});
</script>
</body>
</html>
11. By Mcli
Made by Mcli. Basic JavaScript image comparison slider with Random images on reload. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<style>
body {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.ComparisonSlider {
position: relative;
user-select: none;
}
.ComparisonSlider * {
box-sizing: border-box;
}
.ComparisonSlider > div {
position: absolute;
height: 100%;
width: 100%;
z-index: 1;
overflow: hidden;
}
.ComparisonSlider > div > img {
position: relative;
display: block;
height: 100%;
width: auto;
}
/* the slider */
.ComparisonSlider > span {
position: absolute;
top: 0;
left: calc(50% - 30px);
height: 100%;
width: 60px;
cursor: ew-resize;
z-index: 3;
}
</style>
</head>
<body>
<body id="body">
</body>
<script>
document.addEventListener('DOMContentLoaded', run);
function run() {
const container = document.getElementById('body');
const images = [
"https://source.unsplash.com/random/700x500",
"https://source.unsplash.com/random/800x600"];
const dimensions = { width: 1000, height: 600 };
new ComparisonSlider(container, images, dimensions);
}
//the container will be built with absolute pixel dimensions
class ComparisonSlider {
constructor(node, images, dims) {
//node = DOM parent node
//images = array of image src paths
//dims = object with width and height props
this._node = node;
this._width = validate(dims.width);
this._height = validate(dims.height);
this._container = null;
this._div1 = null;
this._div2 = null;
this._img1 = null;
this._img2 = null;
this._small = null;
this._slider = null;
this._images = images;
this.build(this.node);
//helper
function validate(prop) {
if (Number(prop)) {
return Number(prop);
} else {
return 500;
}
}
}
get node() {
return this._node;
}
get images() {
return this._images;
}
get container() {
return this._container;
}
get width() {
return this._width;
}
get height() {
return this._height;
}
get div1() {
return this._div1;
}
get div2() {
return this._div2;
}
get img1() {
return this._img1;
}
get img2() {
return this._img2;
}
get small() {
return this._small;
}
get slider() {
return this._slider;
}
setSmall(node) {
this._small = node;
this._width = node.offsetWidth;
}
build(node) {
let container = document.createElement('div');
let div1 = document.createElement('div');
let div2 = document.createElement('div');
let img1 = document.createElement('img');
let img2 = document.createElement('img');
//container setup
container.className = "ComparisonSlider";
container.style.width = this.width + 'px';
container.style.height = this.height + 'px';
//hide everything until async load complete
container.style.opacity = 0;
//append
div1.append(img1);
div2.append(img2);
container.append(div1);
container.append(div2);
node.append(container);
//attach to object props
this._container = container;
this._div1 = div1;
this._div2 = div1;
this._img1 = img1;
this._img2 = img2;
//get image paths
let path1 = this.images[0];
let path2 = this.images[1];
let setSmall = this.setSmall.bind(this);
//counter to track when both images sized
let loadCounter = 2;
//when setDims are complete, run buildReady
const buildReady = () => {
//show when ready
this.container.style.opacity = 1;
//next script
this.insertSlider();
};
//determine image widths via async
setDims(img1, path1);
setDims(img2, path2);
//helper get and set dims of image elements
function setDims(elem, url) {
var img = new Image();
img.onload = function () {
elem.width = this.naturalWidth;
elem.height = this.naturalHeight;
elem.src = url;
loadCounter--;
//after both images dims load -- resize container to smaller width
if (loadCounter < 1) {
let w1 = img1.offsetWidth;
let w2 = img2.offsetWidth;
if (w1 < w2) {
resize(w1, w2, img1, img2);
} else {
resize(w2, w1, img2, img1);
}
buildReady();
//helper resize
function resize(small, big, smallNode, bigNode) {
container.style.width = small + 'px';
let dif = big - small;
let offset = dif / 2;
bigNode.style.left = -1 * offset + 'px';
setSmall(smallNode);
}
}
};
img.src = url;
}
}
insertSlider() {
//split and format images
let smallDiv = this.small.parentNode;
smallDiv.style.zIndex = 2;
let w = this.small.offsetWidth;
smallDiv.style.width = w / 2 + 'px';
smallDiv.style.borderRight = "1px solid rgba(0,0,0,0.5)";
//insert slider element
let slider = document.createElement('span');
this.container.append(slider);
this._slider = slider;
this.initializeSlider();
}
initializeSlider() {
let slider = this.slider;
let small = this.small.parentNode;
let fullWidth = this.width;
slider.onmousedown = e => {
e = e || window.event;
e.stopPropagation();
e.preventDefault();
//get cursor x position
var cursor = e.clientX;
//set window mouse events
window.onmousemove = drag;
window.onmouseup = close;
function drag(e) {
e = e || window.event;
e.stopPropagation();
e.preventDefault();
let offset = e.clientX - cursor;
cursor = e.clientX;
//deltas -- displacement
let sliderD = slider.offsetLeft + offset;
let smallD = small.offsetWidth + offset;
//new positions after limit check
let sliderPos = limit(sliderD, -30); //-30 offset for UI
let smallPos = limit(smallD, 0);
//change styles for new position
slider.style.left = sliderPos + 'px';
small.style.width = smallPos + 'px';
//helper to keep position within bounds
function limit(val, off) {
if (val < off) {
return off;
} else if (val > fullWidth + off) {
return fullWidth + off;
} else {
return val;
}
}
}
function close() {
window.onmousemove = null;
window.onmouseup = null;
}
};
}}
</script>
</body>
</html>
12. By Dom Catch
Made by Dom Catch. JavaScript Responsive Comparison Slider. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<style>
.wrapper {
max-width: 1200px;
margin: 0 auto;
}
.fs-comparison-slider {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%;
}
.fs-comparison-slider__bar {
width: 2px;
height: 100%;
position: absolute;
left: 5%;
z-index: 1;
cursor: pointer;
background: linear-gradient(180deg, white 0, white calc(50% - 2rem), rgba(255, 255, 255, 0) calc(50% - 2rem), rgba(255, 255, 255, 0) calc(50% + 2rem), white calc(50% + 2rem), white 100%);
}
.fs-comparison-slider__bar:after {
content: "";
width: 64px;
height: 64px;
background: transparent;
position: absolute;
border-radius: 50%;
border: 2px solid white;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
backdrop-filter: blur(3px);
}
.fs-comparison-slider__control {
width: 100%;
}
.fs-comparison-slider__control input {
width: 100%;
height: 100%;
z-index: 1;
position: absolute;
-webkit-appearance: none;
appearance: none;
outline: none;
pointer-events: auto !important;
background: none;
}
.fs-comparison-slider__control input::-webkit-slider-runnable-track {
height: 100%;
}
.fs-comparison-slider__control input::-webkit-slider-thumb {
appearance: none;
height: 100%;
background: transparent;
cursor: pointer;
width: 0.5em;
box-shadow: none;
}
.fs-comparison-slider__image {
width: 100%;
height: 100%;
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
}
.fs-comparison-slider__image img {
object-fit: cover;
}
.fs-comparison-slider__image--top-image {
clip-path: inset(0 0 0 5%);
}
</style>
</head>
<body>
<div class="wrapper">
<div class="fs-comparison-slider">
<img class="fs-comparison-slider__image" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/74321/dogs-before.jpg"/>
<div class="fs-comparison-slider__bar" data-comparison-slider-bar></div>
<div class="fs-comparison-slider__control">
<input type="range" min="0" max="1000" value="50" data-comparison-slider-control>
</div>
<img class="fs-comparison-slider__image fs-comparison-slider__image--top-image" data-comparison-slider-top-image src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/74321/dogs-after.jpg"/>
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js'></script>
<script>
const ATTR = {
CONTROL: 'data-comparison-slider-control',
BAR: 'data-comparison-slider-bar',
TOP_IMAGE: 'data-comparison-slider-top-image' };
const SELECTOR = {
CONTROL: $(`[${ATTR.CONTROL}]`),
BAR: $(`[${ATTR.BAR}]`),
TOP_IMAGE: $(`[${ATTR.TOP_IMAGE}]`) };
SELECTOR.CONTROL.on("input change", e => {
const percentLeft = `${e.target.value / 10}%`;
SELECTOR.BAR.css({ 'left': percentLeft });
SELECTOR.TOP_IMAGE.css({ 'clip-path': `inset(0 0 0 ${percentLeft})` });
});
</script>
</body>
</html>
13. By asifur
Made by asifur. Basic Image Comparison Slider. Source
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
<style>
body {
display: grid;
place-items: center;
min-height: 100vh;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
--width: 30vw;
--height: 80vh;
}
.container {
position: relative;
width: var(--width);
height: var(--height);
}
.img-after,
.img-before {
position: absolute;
width: var(--width);
height: var(--height);
}
.img-before {
width: 15vw;
overflow: hidden;
}
img {
width: var(--width);
height: var(--height);
object-fit: cover;
}
.slider {
width: 0.2rem;
background-color: white;
height: 80vh;
z-index: 1;
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, 0%);
pointer-events: none;
}
@media (max-width: 700px) {
* {
--width: 70vw;
}
}
</style>
</head>
<body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>image slider</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="img-after">
<img
class="after"
src="https://i.postimg.cc/WzbMWbGn/pexels-jeffrey-czum-2904142-Convert-Image.jpg"
alt=""
/>
</div>
<div class="img-before">
<img class="before" src="https://i.postimg.cc/02P3vpfW/pexels-jeffrey-czum-2904142.jpg" alt="" />
</div>
<div class="slider"></div>
</div>
<script>
//check if a user is visiting with a pc or not
if (window.screen.width <= 800) {
alert("Visit this with pc to see the effect!");
}
const slider = document.querySelector(".slider");
const before = document.querySelector(".img-before");
const after = document.querySelector(".img-after");
const container = document.querySelector(".container");
function dragmyImage(e) {
let xPos = e.layerX;
//take the image container width for different device
let containerSize = container.offsetWidth;
//modify the before image width size with the bar
before.style.width = xPos + "px";
slider.style.left = xPos + "px";
//if the slider bar is close to the image edge pop the bar to the edge
if (xPos < 20) {
before.style.width = 0;
slider.style.left = 0;
}
if (xPos + 20 > containerSize) {
before.style.width = containerSize + "px";
slider.style.left = containerSize + "px";
}
}
container.addEventListener("mousemove", dragmyImage);
//for mobile
container.addEventListener("touchmove", dragmyImage);
</script>
</body>
</html>