Automatic Image Montage with jQuery

Arranging images in a montage like fashion can be a challenging task when considering certain constraints, like the window size when using fullscreen, the right image number to fill all the available space or also the size of the images in use. With the following script you can automatically create a montage, either for a liquid container or a fixed size container (including fullscreen), with the option to fill all the gaps.

Arranging images in a montage like fashion can be a challenging task when considering certain constraints, like the window size when using fullscreen, the right image number to fill all the available space or also the size of the images in use. With the following script you can automatically create a montage, either for a liquid container or a fixed size container (including fullscreen), with the option to fill all the gaps.

Having a white space in the end of the container can, as well, be avoided optionally. The last image of the montage can fill the left space, so that the montage will be left gap-less.

Another option that can be useful in some cases is the possibility to only allow that the height of all images will be the height of the smallest image, avoiding that any picture gets pixelated/enlarged. (The default options will allow the enlargement of smaller images if there is a significantly higher number of larger images in the set.)

The images used in the demos are by Andrey Yakovlev & Lili Aleeva. They are licensed under the Attribution-NonCommercial 3.0 Unported License.

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

The HTML structure

Simply put the images that you want to use in the montage into a container with the following class (the ID is used to call the plugin then):

<div class="am-container" id="am-container">
	<a href="#"><img src="images/1.jpg" title="Image 1"></img></a>
	<a href="#"><img src="images/2.jpg" title="Image 2"></img></a>
	<a href="#"><img src="images/3.jpg" title="Image 3"></img></a>
	...
</div>

The default style that we give to this container and the images is the following:

.am-wrapper{
	float:left;
	position:relative;
	overflow:hidden;
}
.am-wrapper img{
	position:absolute;
	outline:none;
}

Since we don’t define any width for the container, the above example will show the montage in fullscreen.

If you would like to use a container with a fixed width, you can simply add a width.

In case you’d like to have a container with a fixed height and width and with a vertical scrollbar, then you need to add another wrapper around the container:

<div style="width:800px;height:300px;overflow-y:scroll; margin:40px auto;">
	<div class="am-container" id="am-container">
	...
	</div>
</div>

Options

There are several options for this plugin. The default ones are the following:

// If you use percentages (or no width at all)
// for the container's width, then set this to true.
// This will set the body's overflow-y to
// 'scroll' (fix for the scrollbar's width problem)
liquid					: true, 

// Space between images in pixels
margin					: 1,	

// The minimum width that a picture should have
minw					: 70,	

// The minimum height that a picture should have
minh					: 20,	

// The maximum height that a picture should have
maxh					: 250,	

// Alternate the height value for every row.
// If true this has priority over defaults.fixedHeight
alternateHeight			: false,
// The height will be a random value between 'min' and 'max':
alternateHeightRange	: {
	min	: 100,
	max	: 300
},

// If the following value is set, this will
// have priority over defaults.minsize.
// All images will have this height:
fixedHeight				: null,	

// Setting this value will make minw, minh irrelevant.
// Chosen height will be the one of the smallest image
// when this is set to true:
minsize					: false,

// If true, there will be no gap in the end
// of the container. The last image will
// fill any white space left:
fillLastRow				: false

There are quite some possibilities with these options and some of them can be seen in the demos (you can jump to the other demos in each example):

  • Example 1: Fullscreen liquid example with alternating heights, last image will fill the last row. Refresh the browser to see a different arrangement
  • Example 2: Fullscreen liquid example with alternating heights and no margin, last image will fill the last row
  • Example 3: Fullscreen liquid example with alternating heights and bigger margin, last image will fill the last row
  • Example 4: Fixed width container example with fixed height for images. Click “load more” (end of page) in order to see how more images can be added
  • Example 5: Fixed width and height of a wrapper with scrollbar, last image will fill the last row
  • Example 6: Minimum width of images with alternating heights of rows and large margin, last image will fill the last row. Click “load more” (end of page) in order to see how more images can be added
  • Example 7: Liquid container example with fixed height for images. Resize the browser to see the change
  • Example 8: Guarantees that no image will be pixelated by choosing the minimum height available (last image cannot fill the last row). Click “load more” (end of page) in order to see how more images can be added

In each example you can view which options were used to achieve the layout/functionality.

Hope you find it useful, feedback is welcome!

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 in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animations—zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 72

Comments are closed.
  1. Very Nice! Seen something similar recently and was curious about how to execute. Thanks!

  2. Would be great to integrate a lightbox with this, so you can click on each montage image to view a larger version of it.

    Might have to try and give this a go later :).

    Dan

  3. Wonderful. Each time I come to this blog, I always find super creative and useful stuff. Great work, as usual. 🙂

  4. As soon as I saw this tutorial I updated my website to embrace it. It is brilliant for me as a photographer as it does away with boring slideshows. To be able to expand the bottom of the screen is a novel slideshow advance bottom.

    Many thanks again

  5. Very Very Nice!!

    Only a question, wath do you think abouta a feature like a caption for each image taked from the “alt” or “title” attribute of the images?

    • Thank you all for your feedback.
      @Betsy, yes it is possible. I updated the zip file, and changed a bit the structure. The container must have now <a href=”whatever”> around each image, instead of having only images.

  6. Would be nice if some sort of lightbox is integrated so that it can be used as a photo gallery.

  7. Pedro Update Great Thanks! I could integrate LightBox for jQuery! New structure is widely applicable change!

  8. Layout imbalance is caused to resize window.Correct layout was set to resize window in old ver. Oh, close! (>_<).
    I try to compare old and new.

  9. Hi Pedro
    Very nice design and I implemented it as a joomla module but it seems that there is a flaw in margin computation.
    If you set a margin of 10px in all demos, you will see that the right border is not aligned for some rows and that 2*margins width is missing on some rows.
    Current design is only usable with a margin of 0 or 1px, no more. I tried to find the problem but without success.

  10. Hi,

    wonderfull script ! .. But is it normal,when i resize my window,the script freezes,and freezes my browser?… it just stops working.if i want to get the ‘structure’ back i have to reload the page,or sometimes even restart my browser ! .. anyone knows how i can get rid of this issue?

  11. When you resize window,Browser is infinite loop in JQuery. Firefox is shown message ,to cuts process. Old montage is not this ,from Change Image Structure.

  12. in Safari i get also a message to stop,but it crashes right after i push to cancel… anyway,anyone know how to fix this inifinite loop error?

  13. is there any option that we can make the script add pics instead of duplicate them when you click on “load more” ? .. .Just wondering!

  14. Great script, but I think it has a serious bug.

    In your examples, remove the following landscape images (8,39,48) and the remaining images do not display. Put any one of the removed images back, the all the images display. So at least one of these images needs to be in the set for the montage to display.

    I’m have problems with my own set of portrait images – none of them will display.

    • @Tony thanks for noticing. I fixed it now. Please download the zip file and update your js files.
      Thanks!

  15. Thanks Pedro, but there is still a problem. The images display now, but in their original sizes, not reduced.

    • @Tony, I downloaded the zip file, did a test again and it works fine. Removed image 8, 39 and 48 and everything looks OK! (this was not working last time). Did you clean your cache 🙂 ? Can you confirm one more time? Thanks

  16. Pedro, I’m still having the problem with images not resizing to smaller versions when the images 8, 39, and 48 are removed from the example set. I cleared my cache – didn’t change. I’m using the latest jQuery 1.6.4 and Firefox 7.0.1

    • @Tony then I don’t know, cause I am using the same version (firefox and jquery) and it works fine here :S Anyone else having the same problem?? Thanks

  17. AWESOME WORK !! Like everytime !!

    Thanks for the great work you do !
    Anyway, I’ve a question 😉

    Is there a way to force the last picture of the gallery to fit the gap ?

  18. Truly amazing work! I think, you should make your own github repository and let this idea develop and grow.

  19. Evening All,

    I’m currently building a Flickr Import version of this example. I’ve got it working 100% in Firefox and other good browsers but the Montage script isn’t working in IE. Would some just take two mins and have a quick look see if anything is wrong. Any help would be great. URL: http://www.media21a.co.uk/development/unknown/

    • @Adam, try to preload the images before calling the montage plugin, just like it’s done in the examples :

      $imgs.each(function(i) {
      var $img = $(this);
      $(‘<img/>’).load(function() {

      // call montage

      }).attr(‘src’,$img.attr(‘src’));
      });

      Hope it helps!

  20. If .Load dosn’t work how do I go around adding the Montage script to images after load?

  21. that flickr-import would be genious 🙂 and true save for me. cuz now the script (and huge amount of pics) are slowing down my website to damn hard…

  22. Thank you for nice demo! I like it a lot and working on it to adapt to my photographic portfolio!

    One thing I would like to see is to display images in batches, if you have 50+ images loading part is quite long!!!

  23. Thanks Pedro, great script!

    Hope You can help me with Montage and «infinite scroll».

    I have some problem: when new img loading by scrolling, montage is’t working with them.

    Sorry, bad english.

  24. Really, it’d be great if someone could share how they got this to work with a simple Lightbox style script so that when you click an image it enlarges it and fades out the background.

  25. Well, the answer to my question on my own.

    If You want to use Montage and Infinite-Scroll use about such a structure:

    $(function(){

    var $container = $(‘#am-container’),
    $img = $container.find(‘img’).css({ opacity: 0 });

    $container.imagesLoaded(function(){
    $img.animate({ opacity: 1 });
    $container.montage({
    minw : 200,
    alternateHeight : true,
    alternateHeightRange : {
    min : 100,
    max : 250
    },
    margin : 8,
    fillLastRow : true
    });
    }).attr(‘src’,$img.attr(‘src’));
    $img.show();

    $container.infinitescroll({
    navSelector : ‘.nav-previous’, // selector for the paged navigation
    nextSelector : ‘.nav-previous a’, // selector for the NEXT link (to page 2)
    itemSelector : ‘.post’, // selector for all items you’ll retrieve
    loading: {
    finishedMsg: ‘No more pages to load.’,
    img: ‘./i/loading.gif’
    }
    },
    function( newElements ) {
    var $newElems = $( newElements ).css({ opacity: 0 });
    $newElems.imagesLoaded(function(){
    $newElems.animate({ opacity: 1 });
    $container.append( $newElems ).montage( ‘add’, $newElems, {
    minw : 200,
    alternateHeight : true,
    alternateHeightRange : {
    min : 100,
    max : 250
    },
    margin : 8,
    fillLastRow : true
    } );

    });
    }
    );

    });

  26. I try 1st example of the demo with images 175px x 100px, and modify my index.html with alternateHeight to false.

    But the problem is that the last image of each rows don’t manage to reach the right of the screen.

    The image that had to be the last image of the row appears as the 1st image of the next row and redimensioned with the same width that the blank space that appears on the previous row.

    Thank you for your help .

  27. Hi there, has anyone tried to use this in conjunction with any form of Lightbox functionality to enlarge the images??

    Cheers,
    Tyler

  28. Hi there, also has anyone noticed that on some rows of images, the overall row width doesn’t match the majority of the others.. i.e. the nice harsh line down the side of the page is a little bit broken due to some rows?

    Cheers
    Tyler