PHP /**
* 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 : 2 px;
background : # fff ;
transform : translateX ( -50 % ) ;
z-index : 40 ;
pointer-events : none;
}
. ics-slider-handle {
position : absolute;
top : 50 %;
left : 50 %;
width : 20 px;
height : 20 px;
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 2 px # fff , 0 0 4 px # 3857e9 ;
transition : background 0.15 s;
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 8 px 8 px 8 px;
}
. ics-img-title {
color : # fff ;
background : rgba ( 0 , 0 , 0 , 0.70 ) ;
padding : 3 px 10 px;
font-size : 12 px;
border-radius : 0 ;
max-width : 48 %;
overflow : hidden;
text-overflow : ellipsis;
white-space : nowrap;
text-shadow : 0 1 px 4 px # 000 ;
box-sizing : border-box;
transition : opacity 0.18 s;
}
. 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 () ;
}) ;
How To Implement This Solution?