Create an Attractive Before and After Photo Effect with jQuery
- Tweet
- css-html
- javascript
- tutorial
- 24 Jan 2011
- 42
- 8562
Introduction
13 Jan 2011, Australia suffered a catastrophic flood disaster, almost 75% of Queensland was affected. Inland Tsunami in Toowoomba, evacuation of Brisbane city, it was a total chaos in the entire state. Sudden flood which lead to torrential and ferocious flood destroyed homes and killed many. It will take 2 years to recover. If you wish to donate, please visit Queensland Government State Website.
The reason I bought it up because I got this inspiration from this website - Queensland Floods - Before After.
Well, it is saddening to see all the damages the flood did. In the other hand, I also notice the way it presents the before and after photos. It's just so intuitive and simple. So, I have decided to build something similar but with a few of enhancements. I'm going to show you how to build it and how to convert it to plugins. Tested on IE6, 7, 8, Firefox, Chrome and Safari.
You may want to check out the demo now:
Demo 1 Demo 2 - Plugin Download
HTML
I keep the HTML really simple, just a div with 2 images in it. Things you need to know:
- value in ALT attribute will be used as caption
- width and height of the first image will be used for calculation, therefore, it's mandatory to have it defined
This is what you need to use it:
<img src="/img/spacer.gif">However, the content in the div will be totally revamped once it's processed by javascript. This is the real structure:
<div> <div></div> <div></div> <div></div> <img src="/img/spacer.gif">CSS
CSS isn't that complicated as well. I have illustrated how this script going to work which will make it easy to understand
#container {px; margin:0 auto;} /* width and height for the block */ .beforeafter {px; px;} /* The following is the mandatory styling for the plugins */ .ba-mask { /* first image */ position:absolute; top:0; left:0; z-index:100; border-right:4px solid #000; overflow:hidden; box-shadow: 3px 5px 5px rgba(0, 0, 0, 0.6); box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.6); -webkit-box-shadow: 5px 5px 7px rgba(0, 0, 0, 0.6); -moz-box-shadow: 5px 0 7px rgba(0, 0, 0, 0.6); } .ba-bg { /* second image */ position:absolute; top:0; left:0; z-index:0; } .ba-caption { /* caption */ /* mandatory */ position:absolute; bottom:10px; left:10px; z-index:120; /* customizable styling */ background:#000; color:#fff; text-align:center; padding:5px; px; font-family:arial; filter:alpha(opacity=80);-moz-opacity:0.8;-khtml-opacity: 0.8;opacity: 0.8; -webkit-border-radius:5px; -moz-border-radius:5px; border-radius:5px; }Javascript
Alright, some intensive stuff going on over here. The length of the script is pretty long, it's because I'm trying to make this script as flexible as possible and also make the HTML and CSS as simple as possible. You see, once we have the flexibility and simplicity lead to lengthly and complicated code.
I have written a comment to walk you through the whole javascript.
$(document).ready(function() { // Some options for customization var leftgap = 10; /* gap on the left */ var rightgap = 10; /* gap on the right */ var defaultgap = 50; /* the intro gap */ var caption = true; /* toggle caption */ var reveal = 0.5; /* define 0 - 1 far does it goes to reveal the second caption */ // find each of the .beforeafter $('.beforeafter').each(function () { // set current selected item to variable var i = $(this); // get the source of the first image and second image using eq(index) var img_mask = i.children('img:eq(0)').attr('src'); var img_bg = i.children('img:eq(1)').attr('src'); // get the caption for the first image as default caption var img_cap_one = i.children('img:eq(0)').attr('alt'); // get the dimension of the first image, assuming second image has the same dimension var width = i.children('img:eq(0)').width(); var height = i.children('img:eq(0)').height(); // hide the images, not removing it because we will need it later i.find('img').hide(); // set some css attribute to current item for graceful degradation if javascript support is off i.css({'overflow': 'hidden', 'position': 'relative'}); // append additional html element i.append(''); i.append(''); i.append('' + img_cap_one + ''); // set the dimension of appended html element i.children('.ba-mask, .ba-bg').width(width); i.children('.ba-mask, .ba-bg').height(height); // set the images as background for ba-mask and ba-bg i.children('.ba-mask').css('backgroundImage','url(' + img_mask + ')'); i.children('.ba-bg').css('backgroundImage','url(' + img_bg + ')'); // animate to reveal the background image i.children('.ba-mask').animate({'width':width - defaultgap}, 1000); // if caption is true, then display it, otherwise, hide it if (caption) i.children('.caption').show(); else i.children('.ba-caption').hide(); }).mousemove(function (e) { // set current selected item to variable var i = $(this); // get the position of the image pos_img = i.offset()['left']; // get the position of the mouse pointer pos_mouse = e.pageX; // calculate the difference between the image and cursor // the difference will the width of the mask image new_width = pos_mouse - pos_img; img_width = i.width(); // get the captions for first and second images img_cap_one = i.children('img:eq(0)').attr('alt'); img_cap_two = i.children('img:eq(1)').attr('alt'); /* // for debugging purposes $('#debug').html("X Axis : " + e.pageX + " | Y Axis " + e.pageY); $('#debug2').html(i.position()['left']); $('#debug3').html(new_width); */ // make sure it reveal the image and left some gaps on left and right // it depends on the value of leftgap and rightgap if (new_width > leftgap && new_width < (img_width - rightgap)) { i.children('.ba-mask').width(new_width); } // toggle between captions. // it uses the reveal variable to calculate // eg, display caption two once the image is 50% (0.5) revealed. if (new_width < (img_width * reveal)) { i.children('.ba-caption').html(img_cap_two); } else { i.children('.ba-caption').html(img_cap_one); } }); });Convert to Plugin
First of all, what we need to know is the structure of a plugin. I shared about this long time ago, so if you want to know more about it, visit this post - A Really Simple jQuery Plugin Tutorial. Over here I will just paste the structure we going to use in this tutorial:
//You need an anonymous function to wrap around your function to avoid conflict (function($){ //Attach this new method to jQuery $.fn.extend({ //This is where you write your plugin's name pluginname: function() { //Iterate over the current set of matched elements return this.each(function() { //code to be inserted here }); } }); //pass jQuery to the function, //So that we will able to use any valid Javascript variable name //to replace "$" SIGN. But, we'll stick to $ (I like dollar sign :) ) })(jQuery);Alright, the next thing we need to do, mix the plugin stucture with the before after script, and this is the final result:
(function($){ $.fn.extend({ //plugin name - qbeforeafter qbeforeafter: function(options) { var defaults = { defaultgap: 50, leftgap: 10, rightgap: 10, caption: false, reveal: 0.5 }; var options = $.extend(defaults, options); return this.each(function() { var o = options; var i = $(this); var img_mask = i.children('img:eq(0)').attr('src'); var img_bg = i.children('img:eq(1)').attr('src'); var img_cap_one = i.children('img:eq(0)').attr('alt'); var width = i.children('img:eq(0)').width(); var height = i.children('img:eq(0)').height(); i.children('img').hide(); i.css({'overflow': 'hidden', 'position': 'relative'}); i.append(''); i.append(''); i.append('' + img_cap_one + ''); i.children('.ba-mask, .ba-bg').width(width); i.children('.ba-mask, .ba-bg').height(height); i.children('.ba-mask').animate({'width':width - o.defaultgap}, 1000); i.children('.ba-mask').css('backgroundImage','url(' + img_mask + ')'); i.children('.ba-bg').css('backgroundImage','url(' + img_bg + ')'); if (o.caption) i.children('.ba-caption').show(); }).mousemove(function (e) { var o = options; var i = $(this); pos_img = i.offset()['left']; pos_mouse = e.pageX; new_width = pos_mouse - pos_img; img_width = i.width(); img_cap_one = i.children('img:eq(0)').attr('alt'); img_cap_two = i.children('img:eq(1)').attr('alt'); if (new_width > o.leftgap && new_width < (img_width - o.rightgap)) { i.children('.ba-mask').width(new_width); } if (new_width < (img_width * o.reveal)) { i.children('.ba-caption').html(img_cap_two); } else { i.children('.ba-caption').html(img_cap_one); } }); } }); })(jQuery);If we compared it to the non-plugin script, the major difference is how we convert the customizable setting (defaultgap, leftgap, rightgap, caption and reveal) to plugins. That's it, pretty straight forward, just copy and paste and slight modification
How to use Queness' beforeafter plugin
The usage is really simple, this is how you call the plugin:
$(function () { $('.large').qbeforeafter({defaultgap:50, leftgap:0, rightgap:10, caption: true, reveal: 0.5}); $('.small').qbeforeafter({defaultgap:20, leftgap:5, rightgap:10, caption: false}); });Finally...
That's it, a tutorial after a long time. I hope you guys will like it. If you have any questions, suggestion or comment, drop me a message below. Also, help me to spread this post :) Thanks.
About the Author
Kevin Liew is a web designer and developer and keen on contributing to the web development industry. He loves frontend development and absolutely amazed by jQuery. Feel free to say hi to me, or follow @quenesswebblog on twitter.
AdvertisementWe offer all kinds of certification exams including 640-553 dumps and 650-299 certifications. Our guaranteed 646-205 dumps are freely accessible all around the world of 70-667 with testking 220-701.
Show More CommentsLeave a comment
Have something to say? Drop a comment! No HTML tags are allowed in the comment textfield.
42 comments
How do i install the plugin on my word-press ? when i install it it says :The package could not be installed. No valid plugins were found.
Plugin install failed.
I found putting a stop in fixed the issue. Like this.
i.children('.ba-mask').stop().width(new_width);
Awsome plugin. I do a page about a medieval town. I need implement this plugin in my homepage buid on a joomla 1.5. I read a tutorial and I don't know how could I this function on my page. Who wants explain me how can I do this? This plugin allows me show an old and present pictures on my page.
Sorry for my english. I'm from Poland
Thanks
Cheers.
Thanks!
Thanks!
Is there an "easy" to change the code, that you don't have to drag from left to right, but from top to bottom?
Regards
J
www.queness.com/resources/html/beforeafter/index_top.html
i try to use your script, but i have a big problem.
If i load the site the first time, the effekt is not visible / does not work.
If i refresh / reload the site everything ist okay.
Do you have an idea, how i can solve this problem.
If you need a link or something else please send me a message.
Thanks
Mirco
I'm having the same problem with the before/after only working on a second load of each page. Did you ever figure this out? Would love to know what's going on. Thanks.
Best regards,
Athens, Greece
i'm including it to a dental gallery , it will be awesome ..therefore and since i'm just a dentist with tiny skills in webdesign i would like to ask u just two tiny questions if i may:
1 is is possible to include a shadow or frame effect (pure css and html) on the pics without affecting the code .
2 is is possible to include the div in a webpage already build with another css ? or it would be easier to put the whole presentation in a popup if i can center the effet so it comes in the exact middle of the popup window ?
sorry for taking so long of your reading time ..it's just that i'm impressed :)
NB: u own me a free teeth cleaning if u even come to tunisia ;)
1. it's possible, for border or shadow, you need to do this to this css class:
.beforeafter {
border:5px solid #666;
box-shadow:0 0 5px rgba(0,0,0,0.8);
}
2. you can mix this script with other html elements, it shouldn't conflict with the layout. Not so sure about popup, you might get something like fancybox then display this before and after script in an br.
Thanks for that great tutorial!
But i see one requirement for that effect: That the two pictures are as equal as possible, same point of view, same picture angle.
How to do that the best way? Is there any software which can help, or do you have to accomplish that in the moment when you take the "after"-Picture?
Jan
And as a "PLUGIN" why would one want to check the code............just plug it in ;-)
BE WARNED! His site should be CAUGHT YOU IF I CAN lol
Thanks for the tuto,
Nevertheless, i would like to trigger the intro gap after something has been clicked or a div toggle.
Is that possible ? Can you please explain me how to do it.
I'm not literate with javascript and your help would be welcome.
Thanks in advance,
Best regards,
Sam