A simple and clean image comparison slider, fully responsive and touch ready made with css and jquery.
A Pen by Andreas Borgen on CodePen.
A simple and clean image comparison slider, fully responsive and touch ready made with css and jquery.
A Pen by Andreas Borgen on CodePen.
<h1>Image Comparison Slider</h1> | |
<h3> Compare images and any html content</h3> | |
<div class="comparison-container"> | |
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/751678/marioPhoto-2.jpg" alt="marioPhoto 2" /> | |
<div class="caption">And I am the <strong>after</strong> image.</div> | |
<div class="comparison-lhs"> | |
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/751678/marioPhoto-1.jpg" alt="marioPhoto 1" /> | |
<div class="caption">I am the <strong>before</strong> image.</div> | |
</div> | |
</div> | |
<h3> Compare more than two images</h3> | |
<div class="comparison-container"> | |
<img src="https://programming.enthuses.me/assets/codepen/sin-city/scene-comp-3.jpg" alt="" /> | |
<img class="comparison-lhs" data-comparison-splitter="80%" src="https://programming.enthuses.me/assets/codepen/sin-city/scene-comp-2.jpg" alt="" /> | |
<img class="comparison-lhs" data-comparison-splitter="60%" src="https://programming.enthuses.me/assets/codepen/sin-city/scene-comp-1.jpg" alt="" /> | |
</div> |
(function() { | |
"use strict"; | |
function $$(selector) { | |
return Array.from(document.querySelectorAll(selector)); | |
} | |
function syncSize(master, slave) { | |
slave.style.width = master.clientWidth + 'px'; | |
} | |
function getMouseX(parent, e) { | |
const bounds = parent.getBoundingClientRect(), | |
x = e.clientX - bounds.left; | |
return { x, width: bounds.width }; | |
} | |
function initComparer(lhs) { | |
const container = lhs.closest('.comparison-container'), | |
splitPos = lhs.dataset.comparisonSplitter; | |
let dragOffset; | |
//Lock the compared element's width to the original width: | |
window.addEventListener('load', e => syncSize(container, lhs)); | |
window.addEventListener('resize', e => syncSize(container, lhs)); | |
syncSize(container, lhs); | |
//Put the compared element into a resizable wrapper: | |
const lhsWrapper = container.appendChild(document.createElement('div')); | |
lhsWrapper.classList.add('comparison-lhs-wrapper'); | |
lhsWrapper.appendChild(lhs); | |
const dragger = container.appendChild(document.createElement('div')); | |
dragger.classList.add('comparison-dragger'); | |
if(splitPos) { | |
lhsWrapper.style.width = dragger.style.left = splitPos; | |
} | |
//Dragging magic: | |
dragger.onmousedown = (e) => { | |
e.preventDefault(); | |
dragOffset = getMouseX(dragger, e); | |
//console.log(lhs, dragOffset) | |
}; | |
container.addEventListener('mousemove', e => { | |
if(dragOffset) { | |
if(e.buttons === 1) { | |
e.preventDefault(); | |
const newX = getMouseX(container, e), | |
relX = (newX.x - dragOffset.x) / newX.width; | |
lhsWrapper.style.width = dragger.style.left = (Math.max(0, Math.min(relX, 1)) * 100) + '%'; | |
} | |
else { | |
dragOffset = undefined; | |
} | |
} | |
}); | |
} | |
function init() { | |
$$('.comparison-lhs').forEach(initComparer); | |
} | |
init(); | |
})(); |
.comparison { | |
&-container { | |
position: relative; | |
//Make sure the container doesn't stretch horizontally beyond its content: | |
display: table; | |
overflow: hidden; | |
} | |
&-lhs, &-lhs-wrapper { | |
position: absolute; | |
top:0; left:0; | |
} | |
&-lhs { | |
//For inline elements, such as <img> | |
display: block; | |
max-width: none; | |
} | |
&-lhs-wrapper { | |
height: 100%; | |
width: 50%; | |
overflow: hidden; | |
} | |
&-dragger { | |
position: absolute; | |
top:0; left:50%; | |
width: 0; | |
height: 100%; | |
cursor: ew-resize; | |
&::before { | |
content: ''; | |
display: block; | |
width: .4em; | |
height: 100%; | |
margin-left: -.2em; | |
background: rgba(white, .3); | |
} | |
&::after { | |
$button-size: 2.2em; | |
content: '◀ ▶'; | |
display: block; | |
position: absolute; | |
top: 50%; left: 50%; | |
width: $button-size; | |
height: $button-size; | |
margin: $button-size/-2; | |
border-radius: 100%; | |
background: white; | |
text-align: center; | |
line-height: $button-size; | |
white-space: nowrap; | |
} | |
} | |
} | |
/* Page layout - not important */ | |
body { | |
font-family: Georgia, sans-serif; | |
//Weird scrollbar flickering in Chrome when the page content exactly fills the page: | |
overflow-y: scroll; | |
} | |
img { | |
display: block; | |
width: 100%; | |
} | |
.caption { | |
display: inline-block; | |
position: absolute; | |
bottom: .5em; right: .5em; | |
padding: .5em; | |
background: rgba(white, .7); | |
} | |
.comparison-container { | |
//width: 100%; | |
max-width: 1000px; | |
margin: auto; | |
} | |
.comparison-lhs .caption { | |
right: auto; left: .5em; | |
} |
Nice code, but didn't work on movil