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

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:

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

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

Feedback 477

Comments are closed.
  1. Thank you so much for your brilliant work.
    I have a Javascript problem I think!
    No way José to find a solution:
    I have added some cart to sell my tools inside a div and manage to do it with the javaScrip put it should open a MiniCart ticket and it does not. Instead it goes to PayPal directly.
    http://tool.multireflex.eu/dienshop/es-paypal.html

    I would like it to show the MiniCart (Jeff-Harrell) like in this page, that I have done also thanks to you!
    http://tool.multireflex.eu/fichastools/410/es.html

    Could anybody help? I suppose something in the dienshop-grid.js is damaging the correct work of mini cart-mfx.js

    Thanx

  2. Hi! Nice tutorial. I am having a problem with the expander. The expander never opens whenever I click on the grid image. It just takes me to the link that the image has in the href. Help :/ .

    • Ok. Now my issue is that the text and link are not showing up at desktop screen size. Help?

  3. Awesome job, but can you have more than one grid on a scrolling site? I’ve managed to get it working, but it only closes on the first grid. the others leave the X and the indicator image there when it closes…

    any advice would be greatly appreciated 😉

    Grid Test

    • I can’t get it to display any of the details at larger than mobile screen widths! Help!

  4. Hi!

    And thanks for the great tutorial! I scrolled trough the previous comments and tried to modify the grid.js without achieving my goal: Is there any way to modify the grid so that one(in this case the first) item would be expanded by default as the page loads?

    Thanks in advance!

    • Hi Van,

      Just add in a class in your first

      Then add this below after Grid.init();

      setTimeout(function() { $('.first').trigger('click') }, 500);

      Hope this will help

  5. Hi Everyone,

    Does anyone know how to make different grid instances appear upon clicking each grid item? I wanted the inside layout of each box to be different in terms of text formatting, so I isolated and made a different js file for each box. The final step is to get each different java file to activate on clicking its partnering box, but I am not sure how to make this happen.

    For example, I have grid.js which is associated with work-grid and grid3.js which is partnered with work-grid3.

    Thoughts? I appreciate the help 🙂

  6. This is fantastic. Thanks. Does anyone know how it could be possible to close the preview box programmaticly, such as when the ESC key is pressed? I got this far:

    $(document).keyup(function(e) {
    // Close preview on ESC key press
    if (e.keyCode == 27) {
    // What to put here?
    }
    });

    • $(document).keyup(function(e) {
      // Close preview on ESC key press
      if (e.keyCode == 27) {

      //Trigger the close button class on key event
      $(‘.og-close’).trigger(‘click’);

      }
      });

  7. Hi ! thanks for this tutorial ! Is it possible to add two or more pictures in “og-expander-inner” ?

  8. Hi,

    Is there any way to add next and prev link. Also it would be great if someone share how to replace the expanded image with vimeo object

    Thanks
    Kiran

  9. Hello,

    I have added it and it working fine, Now i want to add it 2 times, I mean for different category, as I want it 2 different places on same page, I tried but one is working and another one is not, Please help me …

    I will be thankful to you,

    Thanks,
    Arshi

  10. This is awesome! Is there any way for the Visit Website link to open up a gallery lightbox instead? I’m using this for my portfolio site and I would like to open a series of images for each thumbnail to detail the various steps I took in each project. I tried using prettyPhoto API but I was unsuccessful (I’m a novice when it comes to this stuff).

  11. This is actually very amazing but I have a question, I was recently looking through all this plugins and I was wondering if I can upload it to CMS platform. I tried to download it to WordPress and it didn’t work. I was wondering if i have to code this into a theme or can i just downlond it as a plugin and use it. i really need your help and thank you for this amazingtutorials.

  12. Hi,

    I am trying to add a new item dynamically like this:

    var newitem = ''; newitem += '<a href="http://cargocollective.com/jaimemartinez/" rel="nofollow">'; newitem += ''; newitem += '</a>' newitem += ''; $("#og-grid").append(newitem); var items = []; items.push($("li").last()); Grid.addItems(items[0]); //Grid.init();

    This does not work.
    Also note that I tried to do Grid.init() and even that didn’t work out.

    Can you please guide as to how to achieve this?

    • I had the same problem, maybe I’ve fixed it.

      Looks like $newitems was a Javascript array, not a Jquery array. If you add this line $newitems = $($newitems); it should work.

      function addItems( $newitems ) {

      $newitems = $($newitems); //added
      $items = $items.add( $newitems );
      $newitems.each( function() {
      var $item = $( this );

      $item.data( {
      offsetTop : $item.offset().top,
      height : $item.height()
      } );
      } );

      initItemsEvents( $newitems );

      }

  13. In my above comment the code inside “newitem” has disappeared.

    Inside newitem variable is the string for the entire LI

  14. Hi, first of all thank for sharing the plugin.

    I also need to refresh the call, after adding new items with an infinite scroll plugin. Any clue for a refresh method? A simple recall of Grid.init(); does not work.

    Thanks!

  15. Hello Mary Lou,
    I have problem with positionPreview after load the next page using ajax with window.scroll function to append Grid.addItems(data).

    on grid.js is see case comment

    // 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

    what is the best solution for this case?

  16. Very nice! too bad it doesn’t work out of the box on the iphone. Right after expanding, the preview and description folds back.

    • I think I fix it! I think … I’m not sure haha, after reading so much “grid.js”, erasing and writing more code, it occurred to me clear from line 1 through 41, all code for “debouncedresize” then I tried it on my iphone, and it worked ! the description does not automatically collapse. I’m a newbie, so I’m not sure if delete that code affects. I tried it on my laptop using chrome, safari, firefox and opera, and it works, obviously not in IE, although I have not tried on iPads, Win8, or Android, I hope it works!

      ( Mary Lou! Hope you can tell us if what I did is correct or not … )

  17. Thank you for a great plugin. Please I have one question. When the plugin is used in a responsive mode, there are issues with the height of the og-expander div. In some resolutions, the height leaves a lot of empty space inside the expander. How can one fixed this issue?

  18. Hello Mery, is it possible to use this for content? Its very cool but only for mages. If I use the div over the image-link than it wont wark. It would be beautiful if this could work for the content…

    Best regards. Dmitrij

  19. This is awesome. The only issue i’m having is the website link in the drop down part. I can’t change it or delete it.
    It only shows up in the code when you turn on Live Code, otherwise you can not see it. Any help would be appreciated.

  20. Ignore my lost comment. 🙂 Fixed it.

    Mary Lou, when the thumbs are expanded and then when you closed it, it leaves a massive white space. Which also causes you not to see the next line. This happens in all web browsers not just IE. I have used the code that GitHub has used and that didn’t work either. I have spent a couple of days on this and can not find a solution.
    This is very frustrating. Your help would very appreciated, or anybodies help 🙂

  21. How can I remove that button with an arrow where “visit website” is written

  22. This looks great. Would it be easy to add a hover effect over the thumbnails ?

  23. Hey All,

    Anyone worked out how to have an expanded object automatically opened from the start? I have given each thumbnail an id and tried to open using the trigger event but doesn’t work:
    $(document).ready(function(){
    $(‘#project_thumb_9’).trigger(‘click’);
    });

    Being trying to get this to work for ages!

    Other then that… awesome script!

  24. Anyone know how I’d go about getting the title to appear when you hover over the thumbnail?

  25. This is a great tutorial! Thanks a lot for sharing it. I have though a question, is there a way to implement into WordPress? I tried to, but it seems that the expanded view does not work in WordPress!

    Thank you very much!

  26. For those having issues viewing this on an iPhone (description automatically closing after clicking on the image), update the debouncedresize function with the latest from github.

    https://github.com/louisremi/jquery-smartresize/blob/master/jquery.debouncedresize.js

    Here is the updated code:

    var $event = $.event, $special, resizeTimeout; $special = $event.special.debouncedresize = { setup: function() { $( this ).on( "resize", $special.handler ); }, teardown: function() { $( this ).off( "resize", $special.handler ); }, handler: function( event, execAsap ) { // Save the context var context = this, args = arguments, dispatch = function() { // set correct event type event.type = "debouncedresize"; $event.dispatch.apply( context, args ); }; if ( resizeTimeout ) { clearTimeout( resizeTimeout ); } execAsap ? dispatch() : resizeTimeout = setTimeout( dispatch, $special.threshold ); }, threshold: 150 };

  27. Hello!

    Is it possible to have a thumbnail that opens up to a video rather than a larger image? or even have a project gallery rather than a single image? and how would it be best to add social sharing?

    Thank you in advance!

    Mike

    • Hi Mike,
      I am also asking myself this question. Did you come up with a solution or has anyone responded to your question? Thanks.

  28. I’ve got this working perfectly but when I add more items in, making use of the code in the Add demo, I get a weird issue where the new items don’t seem to scroll to the top of the page before the preview window opening.

    This means that their preview areas are opening off the bottom of the page.

    Any help?

    It seems like the new items need their height offset recalculated or something?

  29. Hi there, thank you for this, however it is not completely responsive when you have a large amount of text in the expandable area and viewing this from mobile platforms, the view website button gets pushed out. And are you able to put images etc.. within the expanded view area? thank you

  30. This is a great plugin! I have one question – how would one go about appending social sharing buttons (ideally the “Addthis” code) into the expanded area for each item? Any help or insight is much appreciated!

  31. Is there any way for the Visit Website link to open up a gallery lightbox / prettyphoto instead?

  32. Hi there.
    I couldn’t find any answers around here about how can I add images into the “data-description” area.
    Is there any way to do it?

    Thanks a million.

  33. Hello,

    First of all, this is awesome, i’m a huge fan of Codrops and check your website out every day. Thanks.

    I was looking for a similar feature as the Google Images. So i decided to go with yours but I struggled to use this in my project so i decided to do a similar thing on my own. I based it on the Superbox plugin of Todd Motto.

    It’s really easy to customize, so check it out : https://github.com/oriongunning/gridder

    I’m very aware that this is no professional plugins, but it work and is easy to use. And if anyone want’s to help me, I’d love you for that.

    • Great work.
      Any idea of how to ad the easy-in and easy-out effects?
      Cheers!!!

    • I tried to use the lightbox but does not work.
      Have some way to make it work?
      Thank you

    • lightbox does not work inside the div “Gridder-content”. Have some way to make it work…

  34. I’ve been struggling with having different preview heights for each item does anyone found how can we setHeights of the preview every time an item is clicked??

  35. Great.
    But I can not expand .og-expnader-inner” without the below get unconfigured.
    is above the .og-expander open.

    ideas???

  36. Hi there.
    This looks really good.
    How can we set the hight to be variable. I want to display long images and more text.

    Thanks.
    Antonio

  37. This is still not working on my iphone5 after your “debouncedresize” update post. Anything else I can try?

    Thanks

    • For temp fix simply wrap debounced resize in if statement that checks for iphone/ipod:
      if (!navigator.userAgent.match(/(iPhone|iPod)/g)) { debouncedresize code }

  38. Hi! Great work.
    I am experimenting problem using this effect over differnt partz of the website.
    Only the first one action works, the others ( defined in different ) do not work.

    Any idea about that?

  39. I tried to use the lightbox but does not work.

    lightbox/ prettyphoto does not work inside the div “Gridder-content”.

    Have some way to make it work?
    Thank you

  40. Hi one help pls,

    i have 3 ‘, ‘ in my HTML code for some Responsive diff size columns.

    so what i have to change in grid.js to work with all 3 ‘ul’ elements…

    Tried changing ID to CLASS in js.. but it raised some issues with expanding div… guide me…

  41. Hi one help pls,
    i have 3 ‘ul‘ lists with different ID’s in my HTML code for some Responsive various size columns.
    so what i have to change in grid.js to get it work with all 3 ‘ul’ elements…
    Tried changing ID to CLASS in js.. but it raised some issues with expanding div… guide me…

  42. Hi guys

    How do I do turn the ‘view website’ text on and off for different images?

    I’d like it on the images that contain my web work but not on images that show my printed artwork.

    Hopefully someone can help.

    Cheers in advance.

    • Hi

      In component.css, add to the end of file :

      .og-details a[href=”#”] {
      display:none;
      }

      Don’t forget in your html file, replace the link where you don’t want to see “view website” by #

  43. Hi,

    Just wondering if any can advise how we can make this work with jQuery.noConflict();? Please advise and help thanks in advance!

    Darren

  44. Good morning. I’m from BRAZIL and I’m trying to use this project.
    I have only one question: Is it posible to put CAPTIONS on mouse over in the pictures ?
    I tried to add this effect – but here there is a conflit with two different effects.