Advertisement
  1. Code
  2. Creative Coding

Image Gallery With Custom Sized Images (Bonus jQuery Plugin)

Scroll to top
Read Time: 10 min

As I promised in my previous article, here is the tutorial on creating a gallery out of the custom sized images. As a bonus you'll learn how to create a basic jQuery plugin to present the larger sized image of the thumbnail in a more appealing way.

If you did not read my previous article about custom image sizes, please read it so it will be easier to understand this tutorial.


Step 1 Decide on Image Sizes

Depending on your theme's layout, and what grid system it uses, you can decide on different image sizes for thumbnails. Before deciding think about how many images you want to have in a row, what is the width of the container where the thumbnails will be displayed, margins, paddings, etc.

I will use a 940 pixel wide, 2 column layout (8/4 ratio) as an example, where the content will be 620 pixels and the sidebar 300 pixels with a 20 pixel left margin. The content area and the sidebar area will have inner padding of 20 pixels. Now a little math: content is 620px wide with padding of 20px, leaving 580px for thumbnails; and displaying 5 thumbnails per line, each having a right margin of 10px so they are not stuck together; 5th image in each line will not have a right margin; thumbnails will be 108px in width and height, and cropped.

The larger sized image will be maximum of 660px wide and 660px tall, they will be resized proportionally without cropping.

You can choose whatever sizes fit your layout, if you decide to change sizes they can be easily regenerated (see previous post on how to do it), and they don't have to be square shaped.


Step 2 Setting Up the Custom Sizes

Edit the functions.php file so it looks something like this:

1
2
add_action( 'after_setup_theme', 'setup' );
3
function setup() {
4
	// ...

5
6
	add_theme_support( 'post-thumbnails' );
7
	add_image_size( 'preview', 108, 108, true ); // thumbnail

8
	add_image_size( 'zoomed', 660, 600 ); // large

9
10
	// ...

11
}

Step 3 Generate Thumbnail List, Excluding the Image Set as Featured

Still in functions.php add the method generate_thumbnail_list:

1
2
function generate_thumbnail_list( $post_id = null ) {
3
	if ( $post_id == null ) return;
4
	$images = get_posts(
5
		array(
6
			'numberposts' => -1,
7
			'post_type' => 'attachment',
8
			'post_mime_type' => 'image/jpeg, image/jpg, image/png, image/gif',
9
			'post_parent' => $post_id,
10
			'orderby' => 'menu_order',
11
			'order' => 'ASC',
12
			'exclude' => get_post_thumbnail_id( $post_id )
13
		)
14
	);
15
	if ( count( $images ) > 0 ) {
16
		echo '<ul class="gallery">';
17
		foreach ( $images as $image ) {
18
			$src = wp_get_attachment_image_src($image->ID, 'zoomed');
19
			echo '<li><a href="' . $src[0] .'">' . wp_get_attachment_image( $image->ID, 'preview' ) . '</a></li>';
20
		}
21
		echo '</ul>';
22
		echo '<div class="clear"></div>';
23
	}
24
}

In content-single.php call the generate_thumbnail_list method, passing the post ID as a parameter.

1
2
<?php the_content(); ?>
3
<h3>Images</h3>
4
<?php generate_thumbnail_list( get_the_ID() ); ?>

The above will output an unordered list, containing links to the larger files and the thumbnail images.


Step 4 Styling the Gallery

Obviously the thumbnails need to be styled, otherwise it is just a plain list of images. Add the following to your existing stylesheet or create a new one and enqueue it:

1
2
.clear {
3
	clear: both;
4
}
5
.gallery {
6
	list-style-type: none;
7
	padding: 0;
8
	margin: 0;
9
}
10
.gallery li {
11
	float: left;
12
	margin: 0 10px 10px 0;
13
}
14
.gallery li:nth-child(5n) {
15
	margin-right: 0;
16
}
17
.gallery a {
18
	float: left;
19
	cursor: pointer;
20
	text-decoration: none;
21
}
22
.gallery img {
23
	float: left;
24
	border: 0;
25
}

This will put images next to each other, leaving some space around them.

At this point clicking on the thumbnail will open the large image on a blank page. This is a good fallback in case the JavaScript is disabled.


Step 5 Open the Images With a jQuery Image Gallery

Style Zoomed Image Gallery

Before writing any JavaScript it would be desirable to know how the large image will be displayed. Here is what I had in mind:

Note: all this will be generated from the jQuery plugin. This is just to show the process of creation.

A transparent overlay on top of all the content, with the image in the middle and the controls on the top right corner. While the image is loading there will be a spinner showing. In the root of the document body a wrapper div will be added, which will contain the links for navigation to the next and previous, a link to close the gallery, and the wrapper around the image where the image will be loaded. This is the minimal HTML code that will be used for the gallery.

1
2
<div id="zoom">
3
	<a href="#next" class="next">Next</a>
4
	<a href="#previous" class="previous">Previous</a>
5
	<div class="close"></div>
6
	<div class="content"></div>
7
</div>

Adding the following style will style the above elements as in the image above (comments are included to explain parts that may not be immediately obvious):

1
2
#zoom {
3
	z-index: 99990; /* high index so it stays on top of all other elements */
4
	position: fixed; /* is fixed so if content is scrolled this stays in the same place */
5
	top: 0;
6
	left: 0;
7
	width: 100%;
8
	height: 100%;
9
	/* creates a transparent background, so the content under it will be visible,

10
	transparency can be adjusted */
11
	background: rgba(0, 0, 0, 0.8);
12
}
13
#zoom .content {
14
	z-index: 99991; /* higher index so the image will stay on top of the overlay */
15
	position: absolute;
16
	/* start initial positioning: will be centered horizontally and vertically */
17
	top: 50%;
18
	left: 50%;
19
	width: 200px;
20
	height: 200px;
21
	margin: -100px 0 0 -100px;
22
	/* end positioning */
23
	/* an animated spinner as background will be visible while the image is loading */
24
	background: #ffffff url('../img/spinner.gif') no-repeat 50% 50%;
25
	border: 20px solid #ececec;
26
	padding: 0;
27
}
28
#zoom img {
29
	display: block;
30
	max-width: none;
31
	background: #ececec;
32
	-moz-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
33
	-webkit-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
34
	box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
35
}
36
#zoom .close {
37
	z-index: 99993; /* higher index so the close will stay above the overlay and image */
38
	position: absolute;
39
	top: 0;
40
	right: 0;
41
	width: 49px;
42
	height: 49px;
43
	cursor: pointer;
44
	background: transparent url('../img/icons/close.png') no-repeat 50% 50%;
45
	opacity: 1;
46
	filter: alpha(opacity=100);
47
}
48
#zoom .previous,
49
#zoom .next {
50
	z-index: 99992; /* higher index so the close will stay above the overlay and image */
51
	position: absolute;
52
	top: 0;
53
	overflow: hidden;
54
	display: block;
55
	width: 49px;
56
	height: 49px;
57
	text-indent: 100%;
58
}
59
#zoom .previous {
60
	right: 100px;
61
	background: url('../img/icons/arrows.png') no-repeat 0 0;
62
}
63
#zoom .next {
64
	right: 50px;
65
	background: url('../img/icons/arrows.png') no-repeat 100% 0;
66
}
67
#zoom .close:hover {
68
	background-color: #da4f49; /* adds a red tint on hover */
69
}
70
#zoom .previous:hover,
71
#zoom .next:hover {
72
	background-color: #0088cc; /* adds a blue tint on hover */
73
}

The outcome of the above:

Now Some JavaScript

The HTML code above will not be needed, it will be generated with JavaScript. Events will be attached for opening, navigating and closing the gallery. Navigating and closing the gallery can be done from the keyboard or using the mouse.

The JavaScript below is also commented to explain what's going on:

1
2
(function($) {
3
	$.zoom = function() {
4
		 // append a gallery wrapper to the document body

5
		$('body').append('<div id="zoom"></div>');
6
		var zoomedIn = false,  // a flag to know if the gallery is open or not

7
		    zoom = $('#zoom'),
8
		    zoomContent = null,
9
		    opened = null; // the opened image element

10
11
		function setup() {
12
			zoom.hide(); // hide it

13
			// add the inner elements, image wrapper, close and navigation links

14
			zoom.prepend('<div class="content"></div>');
15
			zoom.prepend('<div class="close"></div>');
16
			zoom.prepend('<a href="#previous" class="previous">Previous</a>');
17
			zoom.prepend('<a href="#next" class="next">Next</a>');
18
			
19
			zoomContent = $('#zoom .content');
20
			// attach events to the added elements

21
			$('#zoom .close').on('click', close);
22
			$('#zoom .previous').on('click', openPrevious);
23
			$('#zoom .next').on('click', openNext);
24
			
25
			// observe keyboard events for navigation and closing the gallery

26
			$(document).keydown(function(event) {
27
				if (!opened) {
28
					return;
29
				}
30
				if (event.which == 27) {
31
					$('#zoom .close').click();
32
					return;
33
				}
34
				if (event.which == 37) {
35
					$('#zoom .previous').click();
36
					return;
37
				}
38
				if (event.which == 39) {
39
					$('#zoom .next').click();
40
					return;
41
				}
42
				return;
43
			});
44
			
45
			if ($('.gallery li a').length == 1) {
46
				// add 'zoom' class for single image so the navigation links will hide

47
				$('.gallery li a')[0].addClass('zoom');
48
			}
49
			// attach click event observer to open the image

50
			$('.zoom, .gallery li a').on('click', open);
51
		}
52
		
53
		function open(event) {
54
			event.preventDefault(); // prevent opening a blank page with the image

55
			var link = $(this),
56
			    src = link.attr('href'),
57
				// create an image object with the source from the link

58
			    image = $(new Image()).attr('src', src).hide();
59
			if (!src) {
60
				return;
61
			}
62
			$('#zoom .previous, #zoom .next').show();
63
			if (link.hasClass('zoom')) {
64
				$('#zoom .previous, #zoom .next').hide();
65
			}
66
			
67
			// show the gallery with loading spinner, navigation and close buttons

68
			if (!zoomedIn) {
69
				zoomedIn = true;
70
				zoom.show();
71
			}
72
			
73
			// clean up and add image object for loading

74
			zoomContent.empty().prepend(image);
75
			// event observer for image loading, render() will be

76
			// called while image is loading

77
			image.load(render);
78
			opened = link;
79
		}
80
		
81
		function openPrevious(event) {
82
			event.preventDefault();
83
			if (opened.hasClass('zoom')) {
84
				return;
85
			}
86
			var prev = opened.parent('li').prev();
87
			if (prev.length == 0) {
88
				prev = $('.gallery li:last-child');
89
			}
90
			prev.children('a').trigger('click');
91
		}
92
		
93
		function openNext(event) {
94
			event.preventDefault();
95
			if (opened.hasClass('zoom')) {
96
				return;
97
			}
98
			var next = opened.parent('li').next();
99
			if (next.length == 0) {
100
				next = $('.gallery li:first-child');
101
			}
102
			next.children('a').trigger('click');
103
		}
104
		
105
		function render() {
106
			// if the image is not fully loaded do nothing

107
			if (!this.complete) {
108
				return;
109
			}
110
			var image = $(this);
111
			// if image has the same dimensions as the gallery

112
			// just show the image don't animate

113
			if (image.width() == zoomContent.width() && 
114
			    image.height() == zoomContent.height()) {
115
				show(image);
116
				return;
117
			}
118
			var borderWidth = parseInt(zoomContent.css('borderLeftWidth'));
119
			// resize the gallery to the image dimensions before

120
			// displaying the image

121
			zoomContent.animate({
122
				width: image.width(),
123
				height: image.height(),
124
				marginTop: -(image.height() / 2) - borderWidth,
125
				marginLeft: -(image.width() / 2) - borderWidth
126
			}, 300, function(){
127
				show(image);
128
			});
129
130
			function show(image) {
131
				image.fadeIn('fast');
132
			}
133
		}
134
		
135
		function close(event) {
136
			event.preventDefault();
137
			zoomedIn = false;
138
			zoom.hide();
139
			zoomContent.empty();
140
		}
141
		
142
		setup();
143
	};
144
})(jQuery);

After including the above plugin, initialize it by adding the plugin call into the generate_thumbnail_list method:

1
2
function generate_thumbnail_list( $post_id = null ) {
3
	// ...

4
	if ( count( $images ) > 0 ) {
5
		// ...

6
		echo '<script type="text/javascript">jQuery.zoom();</script>';
7
	}
8
}

Example

A real life example of how this works and how it can be used: Zoom jQuery Photo Gallery Plugin demo


References

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.