<figure class="cd-image-container">
	<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/148866/img-original.jpg" alt="Original Image">
	<span class="cd-image-label" data-type="original">Original</span>

	<div class="cd-resize-img"> <!-- the resizable image on top -->
		<span class="cd-image-label" data-type="modified">Modified</span>
	</div>

	<span class="cd-handle"></span>
</figure> <!-- cd-image-container -->
@import "bourbon";

// colors

$color-1: #445b7c; // blue dark
$color-2: #dc717d; // salmon
$color-3: #ffffff; // white

// fonts 

$primary-font: 'Open Sans', sans-serif;

// bounce-in duration

$bounce-in-duration: .7s;

// rem fallback - credits: http://zerosixthree.se/

@function calculateRem($size) {
  $remSize: $size / 16px;
  @return $remSize * 1rem;
}

@mixin font-size($size) {
  font-size: $size;
  font-size: calculateRem($size);
}

// antialiasing mode font rendering

@mixin font-smoothing {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

// breakpoints
   
$S:     320px;   
$M:     768px;     
$L:     1170px;     

// media queries

@mixin MQ($canvas) {
  @if $canvas == S {
   @media only screen and (min-width: $S) { @content; } 
  }
  @else if $canvas == M {
   @media only screen and (min-width: $M) { @content; } 
  }
  @else if $canvas == L {
   @media only screen and (min-width: $L) { @content; } 
  }
}

/* -------------------------------- 

Primary style

-------------------------------- */

*, *:after, *:before {
	@include box-sizing(border-box);
}

body {
	font: {
		size: 100%;
		family: $primary-font; 
	}
	color: $color-1;
	background-color: $color-1;
}

a {
	color: $color-2;
	text-decoration: none;
}

img {
	max-width: 100%;
}

/* -------------------------------- 

Main components 

-------------------------------- */

header {
	position: relative;
	height: 160px;
	line-height: 160px;
	text-align: center;

	h1 {
		@include font-size(22px);
		color: $color-3;
		font-weight: 300;
		@include font-smoothing;
	}

	@include MQ(M) {
		height: 240px;
		line-height: 240px;

		h1 {
			@include font-size(32px);
		}
	}
}

.cd-image-container {
	position: relative;
	width: 90%;
	max-width: $M; 
	margin: 2em auto;

	img {
		display: block;
	}
  
  @include MQ(M) {
    margin: 4em auto;
  }
}

.cd-image-label {
	position: absolute;
	bottom: 0;
	right: 0;
	color: $color-3;
	padding: 1em;
	@include font-smoothing;
	opacity: 0;
	@include transform(translateY(20px));
	-webkit-transition: -webkit-transform .3s $bounce-in-duration, opacity .3s $bounce-in-duration;
	-moz-transition: -moz-transform .3s $bounce-in-duration, opacity .3s $bounce-in-duration;
	transition: transform .3s $bounce-in-duration, opacity .3s $bounce-in-duration;

	&.is-hidden {
		visibility: hidden;
	}

	.is-visible & {
		opacity: 1;
		@include transform(translateY(0));
	}
}

.cd-resize-img {
	position: absolute;
	top: 0;
	left: 0;
	width: 0;
	height: 100%;
	overflow: hidden;
	background: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/148866/img-modified.jpg') no-repeat left top;
	background-size: auto 100%;
	/* Force Hardware Acceleration in WebKit */
	@include transform(translateZ(0));
	-webkit-backface-visibility: hidden;
	backface-visibility: hidden;

	.cd-image-label {
		right: auto;
		left: 0;
	}

	.is-visible & {
		width: 50%;
		/* bounce in animation of the modified image */
		@include animation(cd-bounce-in $bounce-in-duration);
	}
}

@include 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: $color-2 url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/148866/cd-arrows.svg') no-repeat center center;
	cursor: move;
	box-shadow: 0 0 0 6px rgba(#000, .2), 0 0 10px rgba(#000, .6), inset 0 1px 0 rgba(#fff, .3);
	opacity: 0;
	@include transform(translate3d(0,0,0) scale(0));

	&.draggable {
		/* change background color when element is active */
		background-color: $color-1;
	}

	.is-visible & {
		opacity: 1;
		@include transform(translate3d(0,0,0) scale(1));
		-webkit-transition: -webkit-transform .3s $bounce-in-duration, opacity 0s $bounce-in-duration;
		-moz-transition: -moz-transform .3s $bounce-in-duration, opacity 0s $bounce-in-duration;
		transition: transform .3s $bounce-in-duration, opacity 0s $bounce-in-duration;
	}
}
View Compiled
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
    drags($('.cd-handle'), $('.cd-resize-img'), $('.cd-image-container'), $('.cd-image-label[data-type="original"]'), $('.cd-image-label[data-type="modified"]'));

    //upadate images label visibility
    $(window).on('resize', function(){
        updateLabel($('.cd-image-label[data-type="modified"]'), $('.cd-resize-img'), 'left');
        updateLabel($('.cd-image-label[data-type="original"]'), $('.cd-resize-img'), '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 - 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)*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') ;
    }
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js