

Responsive before/after image comparison slider.
/**
* Snippet Name: Before and After Image Comparison
* Snippet Author: coding-bunny.com
* Description: Responsive before/after image comparison slider.
* Version: 1.0.0
*
* USAGE EXAMPLES:
* [image_comparison_slider before="URL1" after="URL2" title_before="BEFORE" title_after="AFTER" show_titles="1"]
*/
add_action('wp_enqueue_scripts', function() {
$css = <<<CSS
.ics-image-comparison-slider {
position: relative;
display: inline-block;
max-width: 100%;
user-select: none;
}
.ics-slider-wrapper {
position: relative;
width: 100%;
}
.ics-before-img,
.ics-after-img {
display: block;
max-width: 100%;
width: 100%;
height: auto;
user-select: none;
pointer-events: none;
position: absolute;
top: 0; left: 0;
}
.ics-slider-handle-line {
position: absolute;
top: 0; bottom: 0;
left: 50%;
width: 2px;
background: #fff;
transform: translateX(-50%);
z-index: 40;
pointer-events: none;
}
.ics-slider-handle {
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
background: #3857e9;
border-radius: 50%;
transform: translate(-50%, -50%);
z-index: 50;
cursor: ew-resize;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 0 2px #fff, 0 0 4px #3857e9;
transition: background 0.15s;
outline: none;
border: none;
}
.ics-slider-handle:after { display: none; }
.ics-slider-range {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
opacity: 0;
z-index: 100;
cursor: ew-resize;
}
.ics-img-titles-row {
position: absolute;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: space-between;
align-items: flex-end;
width: 100%;
z-index: 60;
pointer-events: none;
box-sizing: border-box;
padding: 0 8px 8px 8px;
}
.ics-img-title {
color: #fff;
background: rgba(0,0,0,0.70);
padding: 3px 10px;
font-size: 12px;
border-radius: 0;
max-width: 48%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-shadow: 0 1px 4px #000;
box-sizing: border-box;
transition: opacity 0.18s;
}
.ics-img-title.ics-title-before {
text-align: left;
justify-self: flex-start;
}
.ics-img-title.ics-title-after {
text-align: right;
justify-self: flex-end;
}
CSS;
wp_register_style('ics-inline-style', false);
wp_enqueue_style('ics-inline-style');
wp_add_inline_style('ics-inline-style', $css);
$js = <<<JS
jQuery(document).ready(function($){
function setupSlider(\$container){
var \$wrapper = \$container.find('.ics-slider-wrapper'),
\$beforeImg = \$wrapper.find('.ics-before-img'),
\$afterImg = \$wrapper.find('.ics-after-img'),
\$slider = \$wrapper.find('.ics-slider-range'),
\$handle = \$wrapper.find('.ics-slider-handle'),
\$line = \$wrapper.find('.ics-slider-handle-line'),
\$titleBefore = \$wrapper.find('.ics-img-title.ics-title-before'),
\$titleAfter = \$wrapper.find('.ics-img-title.ics-title-after');
function setWrapperHeight(){
var h = \$beforeImg.height();
\$wrapper.height(h);
\$afterImg.height(h);
}
function setSlider(val){
var percent = val + '%';
\$afterImg.css('clip-path', 'inset(0 0 0 ' + percent + ')');
\$line.css('left', percent);
\$handle.css('left', percent);
var value = parseFloat(val);
if(\$titleBefore.length){
var beforeOpacity = (100 - value)/100;
\$titleBefore.css('opacity', beforeOpacity < 0.03 ? 0 : beforeOpacity);
}
if(\$titleAfter.length){
var afterOpacity = value/100;
\$titleAfter.css('opacity', afterOpacity < 0.03 ? 0 : afterOpacity);
}
}
var imagesLoaded = 0;
function tryInit(){
imagesLoaded++;
if(imagesLoaded>=2) {
setWrapperHeight();
setSlider(\$slider.val());
}
}
\$beforeImg.on('load', tryInit);
\$afterImg.on('load', tryInit);
if(\$beforeImg[0].complete) tryInit();
if(\$afterImg[0].complete) tryInit();
$(window).on('resize', setWrapperHeight);
\$slider.on('input change', function(){ setSlider(this.value); });
var dragging = false;
\$handle.on('mousedown touchstart', function(e){
dragging = true; e.preventDefault();
});
$(document).on('mouseup touchend', function(){ dragging = false; });
$(document).on('mousemove touchmove', function(e){
if(!dragging) return;
var pageX = e.pageX || (e.originalEvent.touches && e.originalEvent.touches[0].pageX);
var offset = \$wrapper.offset().left;
var width = \$wrapper.width();
var percent = ((pageX - offset) / width) * 100;
percent = Math.max(0, Math.min(100, percent));
\$slider.val(percent);
setSlider(percent);
});
\$handle.on('keydown', function(e){
var val = parseInt(\$slider.val(), 10);
if(e.key === 'ArrowLeft' || e.key === 'ArrowDown') {
\$slider.val(Math.max(val - 1, 0)).trigger('input');
} else if(e.key === 'ArrowRight' || e.key === 'ArrowUp') {
\$slider.val(Math.min(val + 1, 100)).trigger('input');
}
});
}
$('.ics-image-comparison-slider').each(function(){ setupSlider($(this)); });
});
JS;
wp_register_script('ics-inline-script', false);
wp_enqueue_script('ics-inline-script');
wp_add_inline_script('ics-inline-script', $js);
});
add_shortcode('image_comparison_slider', function($atts) {
$atts = shortcode_atts([
'before' => '',
'after' => '',
'title_before' => '',
'title_after' => '',
'width' => '100%',
'show_titles' => '0',
], $atts, 'image_comparison_slider');
$before = esc_url($atts['before']);
$after = esc_url($atts['after']);
$title_before = esc_html($atts['title_before']);
$title_after = esc_html($atts['title_after']);
$width = esc_attr($atts['width']);
$show_titles = $atts['show_titles'] === '1' || strtolower($atts['show_titles']) === 'true';
if (empty($before) || empty($after)) {
return '<p><em>Both "before" and "after" URLs are required.</em></p>';
}
ob_start(); ?>
<div class="ics-image-comparison-slider" style="width:<?php echo $width; ?>;">
<div class="ics-slider-wrapper">
<img src="<?php echo $before; ?>" alt="" class="ics-before-img" draggable="false" />
<img src="<?php echo $after; ?>" alt="" class="ics-after-img" draggable="false" />
<?php if($show_titles && ($title_before || $title_after)): ?>
<div class="ics-img-titles-row">
<span class="ics-img-title ics-title-before"><?php echo $title_before; ?></span>
<span class="ics-img-title ics-title-after"><?php echo $title_after; ?></span>
</div>
<?php endif; ?>
<div class="ics-slider-handle-line"></div>
<input type="range" min="0" max="100" value="50" class="ics-slider-range" aria-label="Image comparison slider" />
<span class="ics-slider-handle" tabindex="0" aria-label="Drag to compare images"></span>
</div>
</div>
<?php
return ob_get_clean();
});
Choose one of the following options:
Powered by CodingBunny