A major earthquake struck Japan a few days ago. Out of basic humanitarian concern, one can only hope the people affected get through the difficult period soon and are able to rebuild their homes.

While looking through a special feature about the earthquake, I noticed a very effective before-and-after photo comparison interaction. It lets the viewer move the mouse across an image to reveal the difference between two photos, which is especially useful for showing changes before and after a disaster, renovation, restoration, or any other visual contrast.

The implementation is based on jQuery, and the script is straightforward because it has not been compressed or obfuscated. The main idea is to place the two images into layered div elements, then adjust the width of the top layer according to the mouse position. The effect mainly relies on the use of .after()-style and .before()-style layering logic, along with mouse movement handling.

Here is the core jQuery code:

    jQuery(function(){
        // Loop through all the sets of before and after pics
        jQuery(".beforeafter").each(function(){
            // Set the container's size to the size of the image
            jQuery(this).width(jQuery(this).find("img[rel=before]").attr("width")).height(jQuery(this).find("img[rel=before]").attr("height"));
            // Convert the images into background images on layered divs
            jQuery(this).append("<div class='after'></div>").find(".after").css({"background": "url(" + jQuery(this).find("img[rel=after]").attr("src") + ")", "width": jQuery(this).find("img[rel=after]").attr("width") + "px", "height": jQuery(this).find("img[rel=after]").attr("height") + "px"});
            jQuery(this).append("<div class='before'></div>").find(".before").css({"background": "url(" + jQuery(this).find("img[rel=before]").attr("src") + ")", "width": jQuery(this).find("img[rel=before]").attr("width") - 40 + "px", "height": jQuery(this).find("img[rel=before]").attr("height") + "px"});
            // Add a helpful message
            jQuery(this).append("<div class='help'>鼠标悬停图片上滑动观看</div>");
            // Remove the original images
            jQuery(this).find("img").remove();
            // Event handler for the mouse moving over the image
            jQuery(this).mousemove(function(event){
                // Need to know the X position of the parent as people may have their browsers set to any width
                var offset = jQuery(this).offset().left;
                // Don't let the reveal go any further than 50 pixels less than the width of the image
                // or 50 pixels on the left hand side
                if ((event.clientX - offset) < (jQuery(this).find(".after").width() -50) && (event.clientX - offset) > 50) {
                    // Adjust the width of the top image to match the cursor position
                    jQuery(this).find(".before").width(event.clientX - offset);
                }
            });
            // Fade out the help message after the first hover
            jQuery(this).hover(function(){
                jQuery(this).find(".help").animate({"opacity": 0}, 400, function(){ jQuery(this).find(".help").remove(); });
            });
        });
    });

The script first loops through every .beforeafter container. For each one, it reads the width and height of the image marked with rel=before, then applies those dimensions to the container itself. After that, it creates two absolutely positioned layers: one for the “after” image and one for the “before” image. The original image tags are removed once their sources have been converted into background images.

The real interaction happens in the mousemove event. The script calculates the mouse’s horizontal position relative to the image container and uses that value to change the width of the .before layer. As the layer gets wider or narrower, the viewer sees more or less of the before image, while the after image remains underneath. The code also prevents the sliding boundary from going too close to either edge by limiting movement within a 50-pixel margin.

A short helper message is added on top of the image to tell the user to hover and slide over the picture. Once the user moves onto the image for the first time, that message fades out and is removed.

The accompanying CSS is simple but important. The container needs position: relative and overflow: hidden, while both image layers are placed absolutely at the top-left corner. The .before layer includes a black right border and a shadow, which makes the comparison line more visible as it moves.

    .section {
        margin-top: 50px;
        position: relative;
    }
    .beforeafter { position: relative; overflow: hidden; }
    .before, .after { position: absolute; top: 0; left: 0; }
    .before {
        border-right: 5px solid #000;
        -moz-box-shadow: 1px 0 20px #222;
        -webkit-box-shadow: 1px 0 20px #222;
        box-shadow: 1px 0 20px #222;
        }
    .help {
        position: absolute;
        bottom: 20px;
        right:  70px;
        font: bold 20px/1em Helvetica, Arial, sans-serif;
        color: #FFF;
        opacity: 0.7;
        }

This kind of effect is quite practical whenever two images need to be compared in the same space. It keeps the interface compact, and the mouse-controlled reveal makes the contrast more direct than simply placing two images side by side.