Hover Slide Effect with jQuery

Today we will create a neat effect with some images using jQuery. The main idea is to have an image area with several images that slide out when we hover over them, revealing other images. The sliding effect will be random, i.e. the images will slide to the top or bottom, left […]


View demoDownload source

Today we will create a neat effect with some images using jQuery. The main idea is to have an image area with several images that slide out when we hover over them, revealing other images. The sliding effect will be random, i.e. the images will slide to the top or bottom, left or right, fading out or not. When we click on any area, all areas will slide their images out.

The idea is based on the beautiful Flash based animation on the Yumaki website.

So, let’s start.

The Markup

For the HTML structure we will create a div element with the class and id “hs_container”. Inside we will place the different image areas with all possible images. The first image will have the class “hs_visible” which will make it being displayed on the top of all other images:

<div id="hs_container" class="hs_container">
	<div class="hs_area hs_area1">
		<img class="hs_visible" src="images/area1/1.jpg" alt=""/>
		<img src="images/area1/2.jpg" alt=""/>
		<img src="images/area1/3.jpg" alt=""/>
	</div>
	<div class="hs_area hs_area2">
		<img class="hs_visible" src="images/area2/1.jpg" alt=""/>
		<img src="images/area2/2.jpg" alt=""/>
		<img src="images/area2/3.jpg" alt=""/>
	</div>
	<div class="hs_area hs_area3">
		<img class="hs_visible" src="images/area3/1.jpg" alt=""/>
		<img src="images/area3/2.jpg" alt=""/>
		<img src="images/area3/3.jpg" alt=""/>
	</div>
	<div class="hs_area hs_area4">
		<img sclass="hs_visible" src="images/area4/1.jpg" alt=""/>
		<img src="images/area4/2.jpg" alt=""/>
		<img src="images/area4/3.jpg" alt=""/>
	</div>
	<div class="hs_area hs_area5">
		<img class="hs_visible" src="images/area5/1.jpg" alt=""/>
		<img src="images/area5/2.jpg" alt=""/>
		<img src="images/area5/3.jpg" alt=""/>
	</div>
</div>

Let’s take a look at the style.

The CSS

In our stylesheet, we will define all the areas and their dimensions. Since we will make them absolute, we will also define the positions for each area. Let’s start by defining the main container:

.hs_container{
	position:relative;
	width:902px;
	height:471px;
	overflow:hidden;
	clear:both;
	border:2px solid #fff;
	cursor:pointer;
	-moz-box-shadow:1px 1px 3px #222;
	-webkit-box-shadow:1px 1px 3px #222;
	box-shadow:1px 1px 3px #222;
}

It’s important that we define the overflow as hidden, since we don’t want the sliding images to be shown when they are out of this container.

Each area will also have its overflow hidden and be of position absolute:

.hs_container .hs_area{
	position:absolute;
	overflow:hidden;
}

We position the images inside of the area and make them invisible:

.hs_area img{
	position:absolute;
	top:0px;
	left:0px;
	display:none;
}

The first image will be visible, so we give it the following class:

.hs_area img.hs_visible{
	display:block;
	z-index:9999;
}

And now, we will define the borders and positions of each area:

.hs_area1{
	border-right:2px solid #fff;
}
.hs_area4, .hs_area5{
	border-top:2px solid #fff;
}
.hs_area4{
	border-right:2px solid #fff;
}
.hs_area3{
	border-top:2px solid #fff;
}
.hs_area1{
	width:449px;
	height:334px;
	top:0px;
	left:0px;
}
.hs_area2{
	width:451px;
	height:165px;
	top:0px;
	left:451px;
}
.hs_area3{
	width:451px;
	height:167px;
	top:165px;
	left:451px;
}
.hs_area4{
	width:192px;
	height:135px;
	top:334px;
	left:0px;
}
.hs_area5{
	width:708px;
	height:135px;
	top:334px;
	left:194px;
}

And that’s all the style! Let’s take a look at the JavaScript.

The JavaScript

For the effects, we will be giving the option to use some easing, so don’t forget to include the jQuery Easing Plugin if you make use of that option.
So, let’s first define some variables:

//custom animations to use
//in the transitions
var animations		= ['right','left','top','bottom','rightFade','leftFade','topFade','bottomFade'];
var total_anim		= animations.length;
//just change this one to one of your choice
var easeType		= 'swing';
//the speed of each transition
var animSpeed		= 450;
//caching
var $hs_container	= $('#hs_container');
var $hs_areas		= $hs_container.find('.hs_area');

When we move the mouse over one of the areas we will animate the current image with an animation from our array, so that the next image gets visible. We will use a flag “over” to know if we can animate a certain area since we don’t want two animations to happen at the same time in one area.

We will have a case for each animation and we will define how the animation will behave.

//first preload all images
$hs_images          = $hs_container.find('img');
var total_images    = $hs_images.length;
var cnt             = 0;
$hs_images.each(function(){
	var $this = $(this);
	$('').load(function(){
		++cnt;
		if(cnt == total_images){
			$hs_areas.each(function(){
				var $area 		= $(this);
				//when the mouse enters the area we animate the current
				//image (random animation from array animations),
				//so that the next one gets visible.
				//"over" is a flag indicating if we can animate 
				//an area or not (we don't want 2 animations 
				//at the same time for each area)
				$area.data('over',true).bind('mouseenter',function(){
					if($area.data('over')){
						$area.data('over',false);
						//how many images in this area?
						var total		= $area.children().length;
						//visible image
						var $current 	= $area.find('img:visible');
						//index of visible image
						var idx_current = $current.index();
						//the next image that's going to be displayed.
						//either the next one, or the first one if the current is the last
						var $next		= (idx_current == total-1) ? $area.children(':first') : $current.next();
						//show next one (not yet visible)
						$next.show();
						//get a random animation
						var anim		= animations[Math.floor(Math.random()*total_anim)];
						switch(anim){
							//current slides out from the right
							case 'right':
								$current.animate({
									'left':$current.width()+'px'
								},
								animSpeed,
								easeType,
								function(){
									$current.hide().css({
										'z-index'	: '1',
										'left'		: '0px'
									});
									$next.css('z-index','9999');
									$area.data('over',true);
								});
								break;
							//current slides out from the left
							case 'left':
								$current.animate({
									'left':-$current.width()+'px'
								},
								animSpeed,
								easeType,
								function(){
									$current.hide().css({
										'z-index'	: '1',
										'left'		: '0px'
									});
									$next.css('z-index','9999');
									$area.data('over',true);
								});
								break;
							//current slides out from the top	
							case 'top':
								$current.animate({
									'top':-$current.height()+'px'
								},
								animSpeed,
								easeType,
								function(){
									$current.hide().css({
										'z-index'	: '1',
										'top'		: '0px'
									});
									$next.css('z-index','9999');
									$area.data('over',true);
								});
								break;
							//current slides out from the bottom	
							case 'bottom':
								$current.animate({
									'top':$current.height()+'px'
								},
								animSpeed,
								easeType,
								function(){
									$current.hide().css({
										'z-index'	: '1',
										'top'		: '0px'
									});
									$next.css('z-index','9999');
									$area.data('over',true);
								});
								break;
							//current slides out from the right	and fades out
							case 'rightFade':
								$current.animate({
									'left':$current.width()+'px',
									'opacity':'0'
								},
								animSpeed,
								easeType,
								function(){
									$current.hide().css({
										'z-index'	: '1',
										'left'		: '0px',
										'opacity'	: '1'
									});
									$next.css('z-index','9999');
									$area.data('over',true);
								});
								break;
							//current slides out from the left and fades out	
							case 'leftFade':
								$current.animate({
									'left':-$current.width()+'px','opacity':'0'
								},
								animSpeed,
								easeType,
								function(){
									$current.hide().css({
										'z-index'	: '1',
										'left'		: '0px',
										'opacity'	: '1'
									});
									$next.css('z-index','9999');
									$area.data('over',true);
								});
								break;
							//current slides out from the top and fades out	
							case 'topFade':
								$current.animate({
									'top':-$current.height()+'px',
									'opacity':'0'
								},
								animSpeed,
								easeType,
								function(){
									$current.hide().css({
										'z-index'	: '1',
										'top'		: '0px',
										'opacity'	: '1'
									});
									$next.css('z-index','9999');
									$area.data('over',true);
								});
								break;
							//current slides out from the bottom and fades out	
							case 'bottomFade':
								$current.animate({
									'top':$current.height()+'px',
									'opacity':'0'
								},
								animSpeed,
								easeType,
								function(){
									$current.hide().css({
										'z-index'	: '1',
										'top'		: '0px',
										'opacity'	: '1'
									});
									$next.css('z-index','9999');
									$area.data('over',true);
								});
								break;		
							default:
								$current.animate({
									'left':-$current.width()+'px'
								},
								animSpeed,
								easeType,
								function(){
									$current.hide().css({
										'z-index'	: '1',
										'left'		: '0px'
									});
									$next.css('z-index','9999');
									$area.data('over',true);
								});
								break;
						}	
					}
				});
			});
			
			//when clicking the hs_container all areas get slided
			//(just for fun...you would probably want to enter the site
			//or something similar)
			$hs_container.bind('click',function(){
				$hs_areas.trigger('mouseenter');
			});
		}
	}).attr('src',$this.attr('src'));
});			

And that’s it! We hope you enjoyed the tutorial and find it useful!

View demoDownload source

Previous:
Next:

Tagged with:

Mary Lou (Manoela Ilic) is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

View all contributions by

Website: http://tympanus.net/

Related Articles

Feedback 50

Comments are closed.
  1. 1

    Thank you for sharing.

    Does your plugin run with jquery-mobile ?

    If I use your framework directly, the result is fine with iphone.

    If I use your framework, not directly, but embeded with jquery-mobile, the result is not as expected [images does not fit screen !]
    (div data-role=”page” data-theme=”d” id=”” div data-role=”content” div id=”hs_container” class=”hs_container”)

    Please have a look at http://fiddle.jshell.net/aEkTX/4/show/
    We may resized the screen.

    Suggestion: max-width, width=100% ?

    Any suggestion ?

  2. 2

    Great work !
    Can you help on how to start this automatically and make it repeat with a given interval?

  3. 5

    beautyful work !
    How to get this effect at random in a cycle without hovering when document is ready

  4. 8

    This is brilliant! Wondering if it’s possible to have the individual images click out to urls?… I tried adding a basic anchor to each image but it broke the transition. Any help/insight would be greatly appreciated!

Comments are closed.