Thumbnail Grid with Expanding Preview

A tutorial on how to create a thumbnail grid with an expanding image preview similar to the effect seen on Google Images.

Thumbnail Grid with Expanding Preview

From our sponsor: From online stores to member areas, Squarespace is everything you need to sell anything.

If you have searched images on Google recently, you might have noticed the interesting expanding preview for a larger image when you click on a thumbnail. It’s a really nice effect and it is very practical, making a search much easier. Today we want to show you how to create a similar effect on a thumbnail grid. The idea is to open a preview when clicking on a thumbnail and to show a larger image and some other content like a title, a description and a link.

The interesting part is to calculate the correct preview height and to scroll the page to the right position. We’ll expand the preview in a way so that we can see the respective thumbnail row and cover the rest of the remaining page. Note that we don’t use very large images for the preview in the demo so you might see a lot of empty space on large monitors.

The demo features some amazing artwork by Jaime Martinez.

So let’s start!

The Markup

Initially, we need a thumbnail grid for which we will use an unordered list. Each list item will contain an anchor which will have several data attributes:

<ul id="og-grid" class="og-grid">
	<li>
		<a href="http://cargocollective.com/jaimemartinez/" data-largesrc="images/1.jpg" data-title="Azuki bean" data-description="Swiss chard pumpkin bunya nuts maize plantain aubergine napa cabbage soko coriander sweet pepper water spinach winter purslane shallot tigernut lentil beetroot.">
			<img src="images/thumbs/1.jpg" alt="img01"/>
		</a>
	</li>
	<li>
		<a href="http://cargocollective.com/jaimemartinez/" data-largesrc="images/2.jpg" data-title="Veggies sunt bona vobis" data-description="Komatsuna prairie turnip wattle seed artichoke mustard horseradish taro rutabaga ricebean carrot black-eyed pea turnip greens beetroot yarrow watercress kombu.">
			<img src="images/thumbs/2.jpg" alt="img02"/>
		</a>
	</li>
	<li><!-- ... --></li>
	<!-- ... -->
</ul>

The href value will be used to construct the link in the preview description (this also comes in handy when JavaScript is disabled). The data-largesrc attribute contains the path to the larger image. data-title and data-description contain the title and description, respectively.

When we click on a thumbnail, we want a preview element to appear under the list item. For that we will need to insert an element into the grid. In fact, we will use the list item itself and add the preview element after the anchor:

<li>

	<a href="http://cargocollective.com/jaimemartinez/" data-largesrc="images/2.jpg" data-title="Veggies sunt bona vobis" data-description="Komatsuna prairie turnip wattle seed artichoke mustard horseradish taro rutabaga ricebean carrot black-eyed pea turnip greens beetroot yarrow watercress kombu.">
		<img src="images/thumbs/2.jpg" alt="img02"/>
	</a>
	
	<div class="og-expander">
		<div class="og-expander-inner">
			<span class="og-close"></span>
			<div class="og-fullimg">
				<div class="og-loading"></div>
				<img src="images/2.jpg">
			</div>
			<div class="og-details">
				<h3>Veggies sunt bona vobis</h3>
				<p>Komatsuna prairie turnip wattle seed artichoke mustard horseradish taro rutabaga ricebean carrot black-eyed pea turnip greens beetroot yarrow watercress kombu.</p>
				<a href="http://cargocollective.com/jaimemartinez/">Visit website</a>
			</div>
		</div>
	</div>

</li>

Let’s style everything!

The CSS

Note that the CSS will not contain any vendor prefixes, but you will find them in the files.

So, let’s start with the thumbnail grid. It will be full width and we’ll center the text. In this case this will mean that it will center the thumbnails because we’ll set them to display: inline-block:

.og-grid {
	list-style: none;
	padding: 20px 0;
	margin: 0 auto;
	text-align: center;
	width: 100%;
}

.og-grid li {
	display: inline-block;
	margin: 10px 5px 0 5px;
	vertical-align: top;
	height: 250px;
}

The links and images will be displayed as block elements and we’ll remove some default styling:

.og-grid li > a,
.og-grid li > a img {
	border: none;
	outline: none;
	display: block;
	position: relative;
}

When we click on an item, we will give a special class to the respective list item which will be called og-expanded. We’ll add a little arrow as pseudo-element to the anchor:

.og-grid li.og-expanded > a::after {
	top: auto;
	border: solid transparent;
	content: " ";
	height: 0;
	width: 0;
	position: absolute;
	pointer-events: none;
	border-bottom-color: #ddd;
	border-width: 15px;
	left: 50%;
	margin: -20px 0 0 -15px;
}

The preview itself will have the class og-expander and we’ll position that element absolutely. The initial height of the preview will be 0 and we’ll set the overflow to hidden:

.og-expander {
	position: absolute;
	background: #ddd;
	top: auto;
	left: 0;
	width: 100%;
	margin-top: 10px;
	text-align: left;
	height: 0;
	overflow: hidden;
}

.og-expander-inner {
	padding: 50px 30px;
	height: 100%;
}

The inner division will have some paddings and a height of 100%.

The cross for closing the preview will be created using pseudo-elements, i.e. two rotated lines:

.og-close {
	position: absolute;
	width: 40px;
	height: 40px;
	top: 20px;
	right: 20px;
	cursor: pointer;
}

.og-close::before,
.og-close::after {
	content: '';
	position: absolute;
	width: 100%;
	top: 50%;
	height: 1px;
	background: #888;
	transform: rotate(45deg);
}

.og-close::after {
	transform: rotate(-45deg);
}

.og-close:hover::before,
.og-close:hover::after {
	background: #333;
}

The wrappers for the image and for the details will be 50% wide and we’ll make them float next to each other:

.og-fullimg,
.og-details {
	width: 50%;
	float: left;
	height: 100%;
	overflow: hidden;
	position: relative;
}

The details wrapper will have some padding and we’ll center the image inside of the image wrapper by setting the text-align to center and the image itself to display: inline-block. The image will also have a max-height and max-width of 100% so that it adjusts its size to the surrounding container:

.og-details {
	padding: 0 40px 0 20px;
}

.og-fullimg {
	text-align: center;
}

.og-fullimg img {
	display: inline-block;
	max-height: 100%;
	max-width: 100%;
}

Let’s style the text elements and the link:

.og-details h3 {
	font-weight: 300;
	font-size: 52px;
	padding: 40px 0 10px;
	margin-bottom: 10px;
}

.og-details p {
	font-weight: 400;
	font-size: 16px;
	line-height: 22px;
	color: #999;
}

.og-details a {
	font-weight: 700;
	font-size: 16px;
	color: #333;
	text-transform: uppercase;
	letter-spacing: 2px;
	padding: 10px 20px;
	border: 3px solid #333;
	display: inline-block;
	margin: 30px 0 0;
	outline: none;
}

.og-details a::before {
	content: '2192';
	display: inline-block;
	margin-right: 10px;
}

.og-details a:hover {
	border-color: #999;
	color: #999;
}

The loading element will be in the same container as the image and we’ll not use any images but this CSS-only technique. We’ll create a little circle and set three box shadows: one for making the circle itself look a bit smoother and two for “copying” the element. Then we create an animation that will change the background color and the box shadow colors sequentially:

.og-loading {
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: #ddd;
	box-shadow: 0 0 1px #ccc, 15px 30px 1px #ccc, -15px 30px 1px #ccc;
	position: absolute;
	top: 50%;
	left: 50%;
	margin: -25px 0 0 -25px;
	animation: loader 0.5s infinite ease-in-out both;
}

@keyframes loader {
	0% { background: #ddd; }
	33% { background: #ccc; box-shadow: 0 0 1px #ccc, 15px 30px 1px #ccc, -15px 30px 1px #ddd; }
	66% { background: #ccc; box-shadow: 0 0 1px #ccc, 15px 30px 1px #ddd, -15px 30px 1px #ccc; }
}

Last, but not least, we’ll add two media queries for adjusting the text a bit and for hiding the full image once the screen gets so small that the preview image is not really useful anymore (we’ll also not load it in the JavaScript then).


@media screen and (max-width: 830px) {

	.og-expander h3 { font-size: 32px; }
	.og-expander p { font-size: 13px; }
	.og-expander a { font-size: 12px; }

}

@media screen and (max-width: 650px) {

	.og-fullimg { display: none; }
	.og-details { float: none; width: 100%; }
	
}

That’s all the style. Now, let’s take a look at the JavaScript.

The JavaScript

Let’s start by caching some elements and initializing some variables:

	// list of items
var $grid = $( '#og-grid' ),
	// the items
	$items = $grid.children( 'li' ),
	// current expanded item´s index
	current = -1,
	// position (top) of the expanded item
	// used to know if the preview will expand in a different row
	previewPos = -1,
	// extra amount of pixels to scroll the window
	scrollExtra = 0,
	// extra margin when expanded (between the preview element and the next item row)
	marginExpanded = 10,
	$window = $( window ), winsize,
	$body = $( 'html, body' ),
	// transitionend events
	transEndEventNames = {
		'WebkitTransition' : 'webkitTransitionEnd',
		'MozTransition' : 'transitionend',
		'OTransition' : 'oTransitionEnd',
		'msTransition' : 'MSTransitionEnd',
		'transition' : 'transitionend'
	},
	transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
	// support for csstransitions
	support = Modernizr.csstransitions,
	// default settings
	settings = {
		minHeight : 500,
		speed : 350,
		easing : 'ease'
	};

We will start by preloading all the images (thumbnails) in the grid. We then save the offset top and height for each item in the grid, get the current window’s size, and initialize some events:

	function init( config ) {
		
		// the settings..
		settings = $.extend( true, {}, settings, config );

		// preload all images
		$grid.imagesLoaded( function() {

			// save item´s size and offset
			saveItemInfo( true );
			// get window´s size
			getWinSize();
			// initialize some events
			initEvents();

		} );

	}

	// saves the item´s offset top and height (if saveheight is true)
	function saveItemInfo( saveheight ) {
		$items.each( function() {
			var $item = $( this );
			$item.data( 'offsetTop', $item.offset().top );
			if( saveheight ) {
				$item.data( 'height', $item.height() );
			}
		} );
	}

	function getWinSize() {
		winsize = { width : $window.width(), height : $window.height() };
	}

We will bind the click event for each item (anchor) and for the close button (when the item is opened). When we click on an item, the preview with the large image source and the details will be revealed or hidden if already shown. If we click the close button (cross) on the preview then this preview will be closed too.
We are also binding the resize event for the window, where some values are reset and the preview gets closed (if opened).

	function initEvents() {
		
		// when clicking an item, show the preview with the item´s info and large image;
		// close the item if already expanded.
		// also close if clicking on the item´s cross
		$items.on( 'click', 'span.og-close', function() {
			hidePreview();
			return false;
		} ).children( 'a' ).on( 'click', function(e) {

			var $item = $( this ).parent();
			// check if item already opened
			current === $item.index() ? hidePreview() : showPreview( $item );
			return false;

		} );

		// on window resize get the window´s size again
		// reset some values..
		$window.on( 'debouncedresize', function() {
			
			scrollExtra = 0;
			previewPos = -1;
			// save item´s offset
			saveItemInfo();
			getWinSize();
			var preview = $.data( this, 'preview' );
			if( typeof preview != 'undefined' ) {
				hidePreview();
			}

		} );

	}

With the showPreview function we will basically initialize the Preview object, which in turn will expand and reveal the details and the large version of the image. If a Preview instance is already initialized then we will only update the preview with the new details (if the clicked item is in the same row as the current expanded item) or hide it and initialize / open a new one (if not in the same row).
In order to check if the items are in the same row as the current preview, we use the offset top value of the items.

	function showPreview( $item ) {

		var preview = $.data( this, 'preview' ),
			// item´s offset top
			position = $item.data( 'offsetTop' );

		scrollExtra = 0;

		// if a preview exists and previewPos is different (different row) from item´s top, then close it
		if( typeof preview != 'undefined' ) {

			// not in the same row
			if( previewPos !== position ) {
				// if position > previewPos then we need to take the current preview´s height in consideration when scrolling the window
				if( position > previewPos ) {
					scrollExtra = preview.height;
				}
				hidePreview();
			}
			// same row
			else {
				preview.update( $item );
				return false;
			}
			
		}

		// update previewPos
		previewPos = position;
		// initialize new preview for the clicked item
		preview = $.data( this, 'preview', new Preview( $item ) );
		// expand preview overlay
		preview.open();

	}

The Preview object will have a reference to the currently displayed item (Preview.$item), and the index of the expanded item (Preview.expandedIdx). Note that the expanded item is not necessarily the displayed item. For instance if we click on a second item that is on the same row as the one clicked before then the Preview will be “reused” and the Preview.expandedIdx will not be the index of the Preview.$item. We need to keep the reference to the expanded item so that when the Preview is closed we know which item to “collapse”.

	// the preview obj / overlay
	function Preview( $item ) {
		this.$item = $item;
		this.expandedIdx = this.$item.index();
		this.create();
		this.update();
	}

As the Preview object is initialized we create the necessary structure where the item´s details will be rendered and we append it to the item:

	create : function() {
		// create Preview structure:
		this.$title = $( '<h3></h3>' );
		this.$description = $( '<p></p>' );
		this.$href = $( '<a href="#">Visit website</a>' );
		this.$details = $( '<div class="og-details"></div>' ).append( this.$title, this.$description, this.$href );
		this.$loading = $( '<div class="og-loading"></div>' );
		this.$fullimage = $( '<div class="og-fullimg"></div>' ).append( this.$loading );
		this.$closePreview = $( '<span class="og-close"></span>' );
		this.$previewInner = $( '<div class="og-expander-inner"></div>' ).append( this.$closePreview, this.$fullimage, this.$details );
		this.$previewEl = $( '<div class="og-expander"></div>' ).append( this.$previewInner );
		// append preview element to the item
		this.$item.append( this.getEl() );
		// set the transitions for the preview and the item
		if( support ) {
			this.setTransition();
		}
	}

Then we fill the previous structure with the item´s details (stored in data attributes and the href).
The update function will also be used to just update the content of an existing preview.

	update : function( $item ) {

		// update with new item´s details 
		if( $item ) {
			this.$item = $item;
		}
		
		// if already expanded, remove class "og-expanded" from current item and add it to new item
		if( current !== -1 ) {
			var $currentItem = $items.eq( current );
			$currentItem.removeClass( 'og-expanded' );
			this.$item.addClass( 'og-expanded' );
			// position the preview correctly
			this.positionPreview();
		}

		// update current value
		current = this.$item.index();

		// update preview´s content
		var $itemEl = this.$item.children( 'a' ),
			eldata = {
				href : $itemEl.attr( 'href' ),
				largesrc : $itemEl.data( 'largesrc' ),
				title : $itemEl.data( 'title' ),
				description : $itemEl.data( 'description' )
			};

		this.$title.html( eldata.title );
		this.$description.html( eldata.description );
		this.$href.attr( 'href', eldata.href );

		var self = this;
		
		// remove the current image in the preview
		if( typeof self.$largeImg != 'undefined' ) {
			self.$largeImg.remove();
		}

		// preload large image and add it to the preview
		// for smaller screens we don´t display the large image (the last media query will hide the wrapper of the image)
		if( self.$fullimage.is( ':visible' ) ) {
			this.$loading.show();
			$( '<img/>' ).load( function() {
				self.$loading.hide();
				self.$largeImg = $( this ).fadeIn( 350 );
				self.$fullimage.append( self.$largeImg );
			} ).attr( 'src', eldata.largesrc );	
		}

	}

To reveal the preview we need to set the height of the Preview element and also of the item (to push down the items below). The height of the preview will be the window´s height minus the height of the grid item. To avoid cases where that height could be too small we add the option “minHeight” where we can specify the minimum height needed for the preview element.
As the preview opens we will want to scroll the window so that the preview is completely visible (and if possible, also the item).

	open : function() {

		setTimeout( $.proxy( function() {	
			// set the height for the preview and the item
			this.setHeights();
			// scroll to position the preview in the right place
			this.positionPreview();
		}, this ), 25 );

	}

	setHeights : function() {

		var self = this,
			onEndFn = function() {
				if( support ) {
					self.$item.off( transEndEventName );
				}
				self.$item.addClass( 'og-expanded' );
			};

		this.calcHeight();
		this.$previewEl.css( 'height', this.height );
		this.$item.css( 'height', this.itemHeight ).on( transEndEventName, onEndFn );

		if( !support ) {
			onEndFn.call();
		}

	}

	calcHeight : function() {

		var heightPreview = winsize.height - this.$item.data( 'height' ) - marginExpanded,
			itemHeight = winsize.height;

		if( heightPreview < settings.minHeight ) {
			heightPreview = settings.minHeight;
			itemHeight = settings.minHeight + this.$item.data( 'height' ) + marginExpanded;
		}

		this.height = heightPreview;
		this.itemHeight = itemHeight;

	}

	positionPreview : function() {

		// scroll page
		// case 1 : preview height + item height fits in window´s height
		// case 2 : preview height + item height does not fit in window´s height and preview height is smaller than window´s height
		// case 3 : preview height + item height does not fit in window´s height and preview height is bigger than window´s height
		var position = this.$item.data( 'offsetTop' ),
			previewOffsetT = this.$previewEl.offset().top - scrollExtra,
			scrollVal = this.height + this.$item.data( 'height' ) + marginExpanded <= winsize.height ? position : this.height < winsize.height ? previewOffsetT - ( winsize.height - this.height ) : previewOffsetT;
		
		$body.animate( { scrollTop : scrollVal }, settings.speed );

	}

When closing the preview we reset the heights of the preview element and the expanded item. Once this is done, the preview element / structure gets removed from the DOM.

	close : function() {

		var self = this,
			onEndFn = function() {
				if( support ) {
					$( this ).off( transEndEventName );
				}
				self.$item.removeClass( 'og-expanded' );
				self.$previewEl.remove();
			};

		setTimeout( $.proxy( function() {

			if( typeof this.$largeImg !== 'undefined' ) {
				this.$largeImg.fadeOut( 'fast' );
			}
			this.$previewEl.css( 'height', 0 );
			// the current expanded item (might be different from this.$item)
			var $expandedItem = $items.eq( this.expandedIdx );
			$expandedItem.css( 'height', $expandedItem.data( 'height' ) ).on( transEndEventName, onEndFn );

			if( !support ) {
				onEndFn.call();
			}

		}, this ), 25 );
		
		return false;

	}

And that's it! We hope you enjoyed this tutorial and find it inspiring!

Tagged with:

Stay up to date with the latest web design and development news and relevant updates from Codrops.

Feedback 477

Comments are closed.
  1. Hi there. I love this script but the style: *, *:before, *:after… in the default.css file is messing up the spacing in my navigation bar and my footer (as well as few other places on the page). When I comment the style out then the data title and data description don’t show up in the expanding box. I tried adding a class but it didn’t help.

    Does anyone have any ideas on fixing this?

    • I had the same issue with a couple of elements on my page when i tried to implement this. I found that if you add the following to any elements that are affected fixes it:

      -webkit-box-sizing: content-box;
      -moz-box-sizing: content-box;
      box-sizing: content-box;

      Hope that helps.

    • Thanks, Peter. That helped in some areas but not all. But, I think I can at least work around it now.

    • I had this issue as well and i figured i’d share my fix. It wasn’t an option to leave the * as i had huge navigation and footer issues with that markup.

      Instead of the included code replace it with this:

      .og-details,
      .og-details:after
      .og-details:before {
      -webkit-box-sizing: border-box;
      -moz-box-sizing: border-box;
      box-sizing: border-box;
      padding: 0;
      margin: 0;
      }

      It will apply that only to the div that contains the thumbnails and info, worked for me!

  2. Awesome tutorial! Quick question, how are you controlling the responsive portion? What controls how many columns can display based on screen width? Thanks again for the awesome work!!!

  3. Nice tutorial!
    Can somebody tell me how can i make the height of the preview auto, or based on the big image size? i don’t want it to fill the screen.
    Thanks!

  4. HOW TO ADJUST HEIGHT

    I’ve noticed that a lot of people are asking how to adjust the height. The way that the height is calculated is based on the height of the object being clicked on. I don’t think most of us are capable of modifying it to the point of being auto height, but I have found the function responsible for the height of the expander.

    Line 455:

    calcHeight : function() {

    var heightPreview = winsize.height – this.$item.data( ‘height’ ) – marginExpanded,
    itemHeight = winsize.height;

    if( heightPreview < settings.minHeight ) {
    heightPreview = settings.minHeight;
    itemHeight = settings.minHeight + this.$item.data( 'height' ) + marginExpanded;
    }

    this.height = heightPreview;
    this.itemHeight = itemHeight;

    },
    setHeights : function() {

    var self = this,
    onEndFn = function() {
    if( support ) {
    self.$item.off( transEndEventName );
    }
    self.$item.addClass( 'og-expanded' );
    };

    this.calcHeight();
    this.$previewEl.css( 'height', this.height );
    this.$item.css( 'height', this.itemHeight ).on( transEndEventName, onEndFn );

    if( !support ) {
    onEndFn.call();
    }

    },

    this.itemHeight is the distance from the top of the thumbnail to the bottom of the div. heightPreview is the height of the expanding div. Modify as needed. Me personally, I have fixed heights, so I just changed this.height = heightPreview; to this.height = heightPreview-100

    • do you have any advice for someone who want to change the link visit websit by something Strike (to say no link)?

    • I tried what you said, and it just made a white space under the expander, if I want to make my expander at 400px heigh what should I do?

  5. Is there any way of replacing the image with a Youtube or Vimeo video?

    Ideally once the thumbnail has expanded I’d want a sound cloud or vimeo object embedded.

    How straightforward would that be to do?

  6. Hi,

    Is there any way to open the expanding-preview from another page link? Means I have few links in my home page and I want to open the grid gallery page on click of those links with the corresponding expand preview

    Thanks
    Kiran

  7. Anyone got this working in Internet Explorer 8? The demo loads, the boxes appear correctly too, but when you click a box it moves then opens and immediately closes 🙁

  8. Hi, does anyone know how to add different links to the “Visit Website” or if it’s even possible?

    • I was able to add multiple boxed links like this:

      <a href="#" data-largesrc="assets/images/500px.jpg" data-title="Title here" data-description="Text description here….

      <a href=’#’ rel=”nofollow”>Read about the wins</a>
      <a href=’#’ rel=”nofollow”>More about process</a>”>
      </a>

  9. Can this be made into a plugin for wordpress? Don’t know if this has been asked already but didn’t find anything about it in the article nor the comments.

  10. Hello, I’ve got a little problem using this tutorial, actually I use videoBG to read a video on my background (body). I’ve created a script.js in which I initialize the videoBG, but as soon as I add the line to initialize the grid, I can’t open any thumbs. But the video still works.
    If I delete the js which initialize the videoBG, then I can open the thumbs like in the tutorial.
    I have no clue on what’s wrong in here. If anyone could help, it would be great ! I’m not so good at JS, even if I learn more everyday.

  11. Is there any way for the expanded division to be written whole in html code rather than pulling from grid.js?

  12. There is an issue with IE8. When you expand the content it flickers like its trying to load it but then gets confused, gives up trying and gives you a horrible flicker.

    Any ideas why this might be?

  13. To everyone with IE8 issues.

    There’s no support in IE for “$window.on( ‘debouncedresize’, function() {” … debouncedresize being the issue here.

    A colleague of mine suggested this temporary fix for now:

    ” if(! /Android|webOS|iPhone|iPad|iPod|BlackBerry|if(! /Android|webOS|iPhone|iPad|iPod|BlackBerry|MSIE 8.0/i.test(navigator.userAgent) ) {/i.test(navigator.userAgent) ) { ”

    Adding ” MSIE 8.0 ” to this “if not” fixes the issue where the preview window is opened and then closed immediately.

    I’m going to be testing this out on my IE8 in my VM and will update if I find anything else.

  14. Hi all,

    Is there any way to add multiple images with slider in expanding section (data-largesrc).
    Any help would be appreciable, its a urgent requirement. Thank you.

    By,
    Sijo

  15. Just showcasing where I’ve used this tutorial. If you have any questions on how I got some of it working then feel free to drop me a message via here or my email address ( not sure if I can post this ) kam @ scriptedpixels.co.uk

    This is a client of mine. They had some of this implemented before I started work on it but started from scratch with help from this tutorial and it’s comments/questions/answers.

    This page of their site pulls in products from Magento: http://www.luxdeco.com/discover/

  16. Fantastic script !

    Is there a way though to trigger the close() function of the expander from a custom link on the page? This would really help me !

    Thanks 🙂

  17. Hi, does someone have an idea how to make the description so i can put tags inside it?
    If i want my description to contain some links or tags, or any other tag, what’s the easiest way to do it?

  18. Hi,
    I have implemented it exactly the way, it is specified in the tutorial. I have one huge problem. Clicking on thumbnail, slides the thumbnails on top and opens the desired expansion box. But, after I close it, the slided boxes do not come back to their original place. Also, there is this big gap created between two rows after this, which is taken care only when I refresh the scree. any idea anyone? This is very urgent. Any help would be appreciated. Thanks in advance !!!

  19. Hi , its a really great plugin ,

    i have a little bitt of problem in adding links in full preview part , i need to add a link in its full preview to somewhere else , any idea plzzz…

    thanks

  20. For people who want to add a link around the large image. Find the following in the JS

    this.$fullimage = $( ” ).append( this.$loading );

    And replace with:

    this.$fullimage = $( ‘‘ ).append( this.$loading );

    • This !

      Does anyone know how to add a link around the large image ?

      It’s the last missing element, I managed to get everything else exactly as I wanted. And it is endlessly frustrating to see the answer to the riddle posted twice but being unreadably because part of the code has disappeared …

  21. D’oh .. I realised my previous comment was clearly wrong! Here’s the corrected version!

    For people who want to add a link around the large image. Find the following in the JS

    this . $fullimage = $ ( ‘ ‘ ) .append ( this.$loading )

    And replace with:

    this . $fullimage = $ ( ‘ ‘ ) .append ( this.$loading );

    • Hi Kam,

      Can you help me on hiding the link button if there is no link specified?
      I tried to add a data value : data-link=”<php echo $link", but I can't figure out how to retreive this information in the JS code.

      Thanks 🙂

    • Hi Thomas,

      Not sure if this code will show in the commens but add this on line 390:

      if ( eldata.href ) {
      this.$href.attr( ‘href’, eldata.href );
      };

    • Hi there, Kam,
      Noticed code gets deleted here, interested in you link around image fix.
      Did you post it somewhere else?
      JP

    • Hi JP,

      send me an email – Kam (at) scripted pixels.co.uk and let me know what you’re after .. the commenting system isn’t playing nice for me with any code 🙁

  22. Moderator – can you remove my last two comments, they’re not showing the full code 🙁

  23. Great tutorial!

    Has anyone figured out how/where to tweak the code so that the expanding preview box height will match the height of the image?

    I know it calculates the height of the expanding preview box based on the bottom of the browser, but hw can this be changed to stretch the preview box down below the browser … I’m ok with scrolling to see the rest of the image because I want to use images that are taller and not square.

    I tried playing with the minHeight in the javascript and can change the height for all the preview windows, but can’t get them to match the height of the different images in them.

    Any help would be appreciated 🙂

    Thanks!

    Manny

  24. Hi Mary,

    I am Anish, i tried to use this, but it’s elements are coming from JQuery, can you make it in HTML itself..?

  25. Hey Kam, great work on this 🙂

    One question, I can’t get this to work, any idea?
    Not sure if this code will show in the commens but add this on line 390:

    if ( eldata.href ) {
    this.$href.attr( ‘href’, eldata.href );
    };

    thanks a lot

    • Can you confirm if eldata.href is actually used else where in your code? And the same for the other variables?

      It would be good to see the code on a test area to get an idea of where’s going wrong. Also, console.debug some of the variables to see if they’re being set

  26. Hey,

    I wondering how I can get multiple instance of this to work on a single page. Right now when I open one thumbnail it closes others in separate og-grid containers. Let me know if you have a solution for this 😀

    Thanks for the great plugin.

    Joey Brennan

  27. Hello, do you know how I can add a dinamy class to .og-expander ? I have to create different DIV Height !

    thank you !
    by

  28. Hey All.

    I cannot figure out why but the plugin does not seem to be functional on my website. Nothing executes when I click on the thumbnail except that it follows the link but there is no extended preview happening. I downloaded the source files and attached them directly to the without changing anything. Advice?

    Sarah

  29. Hey Kam,

    thanks (again) for that great script!
    Quick question: do you know how I could insert html into the description?

    Thanks a lot

    • Not too sure what you mean about inserting it in to the description? Do you want to add anchor tags or just HTML markup?

      email me here – kam (at) scriptedpixels (dot) co (uk) … It’ll be easier to help you 🙂

  30. what about when i want to delete an item from the grid. but do not interfere with the function of the other effects. and I want to add a function to delete the item (Grid.removeItems). Can you help me “thank you”

  31. I can’t seem to add a background-image to body… I can change to background-color and such, but can’t add no image..

  32. Hi,
    I have implemented it exactly the way, it is specified in the tutorial. I have one huge problem. Clicking on thumbnail, slides the thumbnails on top and opens the desired expansion box. But, after I close it, the slided boxes do not come back to their original place. Also, there is this big gap created between two rows after this, which is taken care only when I refresh the scree. any idea anyone? This is very urgent. Any help would be appreciated. Thanks in advance !!!

  33. Hi There,
    Great tutorial – 1 issue.. On Ipads / iPods the thumb grid opens for a second then immediately closes quickly 🙁
    I really need this to work for mobile devices. Have you any .js fixes for this.

    Email Me at:
    juneink@gmail.com with any help on this.

    Cheers,
    JUNEINK

  34. Hello, great tutorial and script.

    I was using jquery masonry before I came across your tutorial. This is exactly what I was looking for.

    Is it possible to incorporate infinitescroll into your script? If so can you show me how or if there is something better I am all ears. 🙂

    God bless
    jason

    • In case anyone needs to know how to incorporate infinitescroll with this script:

      Required files:

      <script type="text/javascript" src="PATHTO/jquery.js"></script> <script type="text/javascript" src="PATHTO/thegrid.js"></script> <script type="text/javascript" src="PATHTO/imagesLoaded.js"></script> <script type="text/javascript" src="PATHTO/infinitescroll.js"></script>

      $(function() { Grid.init(); // adding more items $('.og-grid').infinitescroll({ navSelector : '.pagination', // selector for the paged navigation nextSelector : '.pagination a', // selector for the NEXT link (to page 2) itemSelector : 'li', // selector for all items you'll retrieve loading: { finishedMsg: 'No more posts to load.', img: 'PATH TO YOUR GIF LOADER IMAGE' } },function( newElements ) { // hide new items while they are loading var $newElems = $( newElements ).css({ opacity: 0 }); // ensure that images load before adding to the grid layout $newElems.imagesLoaded(function(){ // show elems now they're ready $newElems.animate({ opacity: 1 }); var $items = $( newElements ).appendTo( $( '#og-grid' ) ); Grid.addItems( $items ); }); } ); });

  35. Shoot I’m sorry I don’t know what I am doing wrong, but when I click a thumbnail the og-details don’t show, only what is in the a tag shows. Once I actually tried to change what appeared within the details area I noticed it wasn’t the details I was seeing but the a tag attributes. Also I am confused because when I look at the source code straight from the demo I don’t even see the “og-details” class, I pasted it into my code but it still doesn’t work.

    Basically I want to utilize the details area so that I can add more info than I could just using the a tag. Once you click on the thumbnail I would like to show a couple of paragraphs and several photos.

  36. This is exactly what I’m looking for! But I got a prob when I tried including this in Foundation 4. There seems to be a conflict with the jQuery libraries. Anybody here able to uses this with Foundation? HELP!

  37. Oh, I forgot to include the errors. It says:

    Uncaught TypeError: Cannot set propoerty ‘debouncedresize’ of underdefined
    Uncaught TypeError: Cannot call method ‘init’ of undefined

    Thanks!!

  38. I had the same issue like some of you guys, i’ve wanted to add an auto height to the box based on the conten’s height. Here is my solution:

    in the js file, line 465-466:

    change this:
    this.height = heightPreview;
    this.itemHeight = itemHeight;

    to this:
    this.height = settings.minHeight;
    this.itemHeight = settings.minHeight + this.$item.data( ‘height’ ) + marginExpanded;

    For me, it works like a charm ^^

  39. Hi, just wondering if it is possible to give every <a> element has a unique # value, and when each time the thumb gets clicked, we get a unique address , like yourwebsite.com/#story1
    So we can bookmark each expander and use back button to navigate through ?
    Any ideas will be appreciated.

  40. I have seen this question asked a couple of times but no answer has been given. I added a function to insert a div with the date for each month in my grid. clicking the thumbnails to open the preview works great but when closing the preview I have a huge gap where the preview was and the indicator arrow still shows. Obviously once the div is added your script breaks. Any ideas of why and how I can resolve this?

    Additional NOTE: If I insert the div using .append or .prepend everything works as it should. This is because it adds the div inside one of the s This problem only occurs when I use .before or .after to insert the div.

    God bless
    jason

  41. Hello,
    I am kind of new on this, but I need to do 2 things:
    a) Add a link to the large image. It should be a different link for each one of the expanding.
    b) When expanded, I need to replace every title for a different image.

    Is that possible? Any help on this? please.

  42. To any future people:
    Please don’t use this unless you really know jQuery. Why?
    1. It’s not going to be supported and updated. – if you want to, you need to know jQuery.
    2. I’m really not a fan of a lot of it. Adding the html in the javascript is very obtrusive. Adding all the html in data attributes is ridiculous. And there’s a few other minor things I subjectively am not a fan of.
    3. If you don’t know jQuery expanding it to your needs won’t work. Use a plugin that’s well supported and does everything you want off the bat.

    • Totally agree with you David, I usually don’t have much time for contributing on open source projects but in this case I made some updates to the code and I’m hoping to get the github link for this project to give it some much needed love as I find this to be a neat gallery for people just wanting to have a quick gallery without having to be a lightbox.

  43. Hi, is there a way to include the content of an external page into the expanded view?
    Thanks

  44. Hi is there any way by which we can remove the zoom in and zoom out transitions of the expander images. I want to have simple fadeIn and fadeOut transitions.

    Thanks for your help.