





Today, we will look at how to create a responsive gallery with directional-aware hover. By directional-aware hover I mean that the title and description of the image will slide in from the direction your mouse entered the image.

The source code as well as a live demo can be seen below.

Live demo Download source

Pretty cool huh? Let’s go over the topics we will cover in this tutorial while we create this responsive gallery with directional-aware hover.

You will learn:

How to use <figure> and <figcaption> to display images and descriptions

How to calculate the side where our mouse entered an image with JavaScript

How to tile images in columns (instead of rows)

How to use CSS3 transition to slide an element

So let’s dive right in!

The HTML5 Markup for images with descriptions

We will display our images and descriptions using the figure and figcaption tags.

Inside of the figcaption we will place a h1 for the title and a p for further description of the image. We will also require a div with a description class for styling reasons.

The gallery images will also be contained inside of a div with a gallery ID

<div id="gallery"> <figure class="gallery-img"> <img src="[IMAGE]"> <figcaption> <div class="description"> <h1>Title</h1> <p>Lorem ipsum dolor sit amet</p> </div> </figcaption> </figure> ... </div>

Dividing the gallery into columns

So now that we have our HTML down, let’s make our images tile into columns by using CSS3’s cool column-count property.

#gallery { column-count: 5; column-gap: 0; }

We also set the column-gap property to 0. This makes sure our images will be placed right next to each other.

Now, 5 columns is probably a bit much for smaller screens. So let’s use media queries to adjust the number of columns to the browser size.

@media (min-width: 768px) and (max-width: 1199px) { #gallery { column-count: 3; } } @media (max-width: 767px) { #gallery { column-count: 1; } }

Of course, we also need to style our figure elements to make sure our images fit inside the columns. We also want to style our figcaption to act as a semi-transparent overlay with the title on the top and description on the bottom. Aside from that we will give our figcaption position:absolute so that we can use other classes to position it for sliding.

Last but not least, we add overflow:hidden to the figure in order to make sure that our description won’t appear over other images.

#gallery .gallery-img { width: 100%; position: relative; margin: 0; overflow: hidden; } #gallery .gallery-img img { width: 100%; display: block; } #gallery .gallery-img figcaption { background: rgba(0,0,0,0.5); position: absolute; width: 100%; height: 100%; } #gallery .gallery-img figcaption .description { position: relative; width: 100%; height: 100%; } #gallery .gallery-img figcaption .description h1 { padding: 20px; font-family: helvetica, arial, sans-serif; color: white; font-size: 45px; text-align: center; } #gallery .gallery-img figcaption .description p { font-family: helvetica, arial, sans-serif; color: white; text-align: center; position: absolute; width: 100%; bottom: 50px; }

For the sliding of the figcaption element, we will need to initialize our positioning. The figcaption itself already has position:absolute on it. For this I chose to work with CSS classes to make it easier to customize and keep my JavaScript cleaner, but you can also add the CSS with jQuery instead of toggling the classes with jQuery.







Important note: For the left and right class, we also initialize the top property. If we don’t do this, the figcaption will not appear.

#gallery .gallery-img.left figcaption { top: 0; left: -100%; } #gallery .gallery-img.right figcaption { top: 0; right: -100%; } #gallery .gallery-img.top figcaption { top: -100%; } #gallery .gallery-img.bottom figcaption { bottom: -100%; } #gallery .gallery-img.left.animated figcaption { left: 0; } #gallery .gallery-img.right.animated figcaption { right: 0; } #gallery .gallery-img.top.animated figcaption { top: 0; } #gallery .gallery-img.bottom.animated figcaption { bottom: 0; }

The idea here is to use jQuery to add a class according to the direction from where your mouse entered and also add an animated class to make it animate.

In order for the animation to work, we add a transition to the figcaption of the animated class.

#gallery .gallery-img.animated figcaption { transition: 0.3s ease-out; }

(Optional) Wait until images are loaded

You may have realized by now that the positioning could get a bit funky until the images have all loaded.

We can solve this by using the imagesLoaded plugin which will enable us to use an event to detect if our images have loaded. We could then add a loading div and make it dissapear once the images have loaded.

$('#gallery').imagesLoaded(function() { $('#spinner').fadeOut(500, function() { $('#gallery').animate({'opacity' : '1'}, 500); }); });

Calculating the direction from where the mouse entered the image

In order to make our gallery hover effect directional-aware, we need to calculate where our mouse entered the image and add a class to the element accordingly.

This means that if we entered from the left, we will add a left class to the figure. To calculate the direction and return the direction as a string, we use the following JavaScript function.

var getDir = function( elem, e ) { /** the width and height of the current div **/ var w = elem.width(); var h = elem.height(); var offset = elem.offset(); /** calculate the x and y to get an angle to the center of the div from that x and y. **/ /** gets the x value relative to the center of the DIV and "normalize" it **/ var x = (e.pageX - offset.left - (w/2)) * ( w > h ? (h/w) : 1 ); var y = (e.pageY - offset.top - (h/2)) * ( h > w ? (w/h) : 1 ); /** first calculate the angle of the point, add 180 deg to get rid of the negative values divide by 90 to get the quadrant add 3 and do a modulo by 4 to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/ var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180 ) / 90 ) + 3 ) % 4; /** return the direction **/ switch(direction) { case 0: return 'top'; break; case 1: return 'right'; break; case 2: return 'bottom'; break; case 3: return 'left'; break; } }

And lastly, we will want to add and remove this class from our images, as well as the animated class.

Important note: In order for the transition property to work here, we need to add the animated class after we add the directional class. We can safely do this by using setTimeout()

setTimeout(function(){ $(img).addClass("animated"); }, 1);

Now let’s put this all together

var lastDirection; $(function(){ $('#gallery').imagesLoaded(function() { $('#spinner').fadeOut(500, function() { $('#gallery').animate({'opacity' : '1'}, 500); }); }); $('.gallery-img').bind('mouseenter',function(e){ var img = this; lastDirection = getDir($(this), e); $(img).addClass(lastDirection); setTimeout(function(){ $(img).addClass("animated"); }, 1); }); $('.gallery-img').bind('mouseleave', function(e){ $(this).removeClass(lastDirection).removeClass('animated'); }); });

That’s all there is to it! We now have made a responsive gallery with directional-aware hover.