Adaptive Thumbnail Pile Effect with Automatic Grouping

An experimental jQuery plugin that will group thumbnails by a shared data-attribute into a pile. When clicking on the pile, the thumbnails that belong to that pile will be spread into a grid using CSS transitions.
Adaptive Thumbnails Pile Effect with Automatic Grouping

From our sponsor: Don't spend all day sending messages. Automatically reach out to fans based on how they behave.

This experimental jQuery plugin allows the automatic grouping of thumbnails using a pile effect. The thumbnails will group according to their shared data-pile attribute and once clicked, the pile will disperse and its thumbnails fly to their positions. The thumbnails can be slightly rotated or positioned with a delay.

The grid itself is adaptive, meaning that if there is not enough horizontal space considering the width and the gutter of the items, the column count will decrease and the grid will re-order.

The demo features some Dribbble shots of the following artists:

Please note that the CSS transforms and transitions only work in browsers that support them.

There is a simple jQuery animate fallback for browsers that don’t support transitions.

For using the plugin, an unordered list with the class “tp-grid” is expected, i.e. in our demo we use:

<ul id="tp-grid" class="tp-grid">

	<li data-pile="Group 1">
		<a href="#">
			<span class="tp-info">
				<span>Some title</span>
			<img src="images/1.jpg" />

	<li data-pile="Group 2">
		<!-- ... -->

	<li data-pile="Group 1,Group 2">
		<!-- ... -->

	<!-- ... -->


The data-pile attribute will contain the name of the group that the item belongs to. Note that an item can belong to more than one group.

The plugin can be called like this:

$( '#tp-grid' ).stapel();


The following default options are available:

$.Stapel.defaults = {

	// space between the items
	gutter : 40,

	// the rotations degree for the 2nd and 3rd item 
	// (to give a more realistic pile effect)
	pileAngles : 2,

	// animation settings for the items of the clicked pile
	pileAnimation : { 
		openSpeed : 400,
		openEasing : 'ease-in-out',
		closeSpeed : 400,
		closeEasing : 'ease-in-out'

	// animation settings for the other piles
	otherPileAnimation : { 
		openSpeed : 400,
		openEasing : 'ease-in-out',
		closeSpeed : 350,
		closeEasing : 'ease-in-out'

	// delay for each item of the pile
	delay : 0,

	// random rotation for single items
	randomAngle : false,

	// callback functions
	onLoad : function() { return false; },
	onBeforeOpen : function( pileName ) { return false; },
	onAfterOpen : function( pileName, totalItems ) { return false; },
	onBeforeClose : function( pileName ) { return false; },
	onAfterClose : function( pileName, totalItems ) { return false; }


The basic styling is defined in the stapel.css file and you can see an example of some additional styling for the demos in custom.css.


Check out the demos to see some different configurations in action:

Tagged with:

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

CSS Reference

Learn about all important CSS properties from the basics with our extensive and easy-to-read CSS Reference.

It doesn't matter if you are a beginner or intermediate, start learning CSS now.

Feedback 137

Comments are closed.
  1. Hi folks,

    I’m playing with this beautiful effect and I found that when the page is too big, the stack opens and the browser stays where it was, so the open stack can get out of sight. I just added at the bottom of _openPile an animation to scroll to the top of the page (can be the stack container) like this:

    /* scroll to top */
    var top = self.el.offset().top;
    $("html, body").animate({ scrollTop: top }, 100); // You can use 0 to scroll to the top of the page, you get the idea.

    Hope somebody finds it useful.

    • Good morning!
      dude, can you tell me where do I stick this code? because really when you surf and back to home, and selects the next block, it does not start at the top!

    • I added just $("html, body").animate({scrollTop: $("#close").offset().top}, 400); right after onBeforeOpen : function( pileName ) { in function calling at the bottom of the body and it works fine.

  2. Hi can you please tell me how to hide Grouping Functionality from above demo… actually i want to display list of photo with pile effect only.

  3. Hi,

    This is a beautiful effect. Does anyone know if it would be possible to add isotope/masonry to improve the layout?

  4. Nice effect, I ‘d like to ask you something…

    In the piles if you remove the background of the title, on IPAD appears all the rest of the titles… is there something to hide the rest of titles and just show the most-top title of the pile.

    Thanks again.

  5. This is pretty nice. Seems simple enough to use….but for some reason I can’t get it to work on localhost. It just does the loading boxes but that’s it. I’ve verified that all the necessary scripts, css and images are in place.

    I can get it working on a live server, no problem. Is there a trick to get it working on a localhost or am I just missing something? Any info appreciated.

  6. Is it possible to inverse the order of the pile. The top thumbnail of the pile correspond to the first on the top left thumbnail unstacked?

    Great plugin!

  7. Pedro,

    I’ve tried to create a page with 107 images (each one is about 30k) on
    The animation is just amazing, but load time is something that kills the entire idea…

    I’m wondering if it’s possible dynamically load images (or even whole elements) while visitor did not clicked specific category? And if she/he did, load chosen category items first?

    I have some dev. resources if assistance needed. Would you like to make extra mile in the plugin development?

    Please drop me a line,

  8. @ Larry & Brian (can’t seem to respond directly to your comment) I was able to get lightbox to enlarge images like this:


  9. Hi, this is awesome and thank you very much for the tutorial. I would appreciate if someone can tell me how to remove the gutter size after the last item in a row.

    I have 4 images in a row and its look odd when there is an empty space as gutter after the last image.


  10. Thank you for this amazing effect, I was wondering if it’s possible to add some kind of hover effect when user hovers on pile? like the opacity option in css. Let me know, thanks.

  11. Sorry for the double comment, I also found one issue. If on the showcase you got 2 rows, and then you open a pile that contains only 1 row, then the bottom row of the other piles (which is invisible) is still clickable. Is there any way to fix that?

  12. Wow, I actually fixed that issue (where invisible piles are still clickable which can mess functionality of this great script).

    CTRL +F to find the following lines in jquery.stapel.js and add z-index:

    this._applyTransition( $item, { opacity : 0}, this.options.otherPileAnimation.closeSpeed );

    replace it with:

    this._applyTransition( $item, { opacity : 0, 'z-index' : '-1' }, this.options.otherPileAnimation.closeSpeed );


    this._applyTransition( $item, { opacity : 1}, this.options.otherPileAnimation.openSpeed, function( evt ) {


    this._applyTransition( $item, { opacity : 1, 'z-index' : '0' }, this.options.otherPileAnimation.openSpeed, function( evt ) {

  13. Instead of ‘z-index’ use ‘visibility’ : ‘hidden’ and ‘visible’, it works better (had some issues with z-index). Again sorry for the multiple comments.