Gamma Gallery: A Responsive Image Gallery Experiment

Gamma Gallery is an experimental responsive image gallery that attempts to provide an adjustable responsive images approach taking its grid layout and the full slideshow view into account.

Gamma Gallery: A Responsive Image Gallery Experiment

Creating a truly responsive image gallery can be a very tricky and difficult thing. There are so many factors to consider like the layout and the features, and so many choices to make when it comes to delivering a good viewing experience for every device. Gamma Gallery is an attempt to create an image gallery that uses a similar responsive images approach to the proposed picture element. Focused on providing suitable image sizes for both, the fluid grid thumbnails and the full image view, the selection of images also depends on container dimensions and not solely on the window size. In some cases it might even be reasonable to load larger thumbnails for a smaller device if we, for example want to show less columns in a grid. So, smaller windows don’t necessarily mean smaller thumbnails.

Gamma Gallery uses David David DeSandro’s Masonry in a fluid mode where column numbers are defined depending on the grid container sizes.

Inspired by Picturefill from Scott Jehl, the responsive images approach that mimics the picture element, we’ve come up with the following HTML structure for defining different image sizes:

<div class="gamma-container gamma-loading" id="gamma-container">

	<ul class="gamma-gallery">
		<li>
			<div data-alt="img01" data-description="<h3>Assemblage</h3>" data-max-width="1800" data-max-height="2400">
				<div data-src="images/xxxlarge/1.jpg" data-min-width="1300"></div>
				<div data-src="images/xxlarge/1.jpg" data-min-width="1000"></div>
				<div data-src="images/xlarge/1.jpg" data-min-width="700"></div>
				<div data-src="images/large/1.jpg" data-min-width="300"></div>
				<div data-src="images/medium/1.jpg" data-min-width="200"></div>
				<div data-src="images/small/1.jpg" data-min-width="140"></div>
				<div data-src="images/xsmall/1.jpg"></div>
				<noscript>
					<img src="images/xsmall/1.jpg" alt="img01"/>
				</noscript>
			</div>
		</li>
		<li> <!-- ... --> </li>
		<!-- ... -->
	</ul>

	<div class="gamma-overlay"></div>

</div>

Depending in which viewing mode we are, thumbnail grid view or full image view, the choice of the fitting image will depend on either the list item’s size or the whole viewport size. Let’s call that the “container size”. An “xsmall” image will be chosen if the container size is less than 140 pixels. A “small” image is picked if the container is wider than 140 pixels (data-min-width=”140″). A “medium” image is chosen if the container is wider than 200 pixels and so on.

Because we have a “fluid” image approach where we define the max-width of the image to be 100%, we will fit the image in its container if the image is bigger than the container. For that, our images will have the sizes that are defined in their consecutive (upper) step. For example, the “large” sized image will have a width of 700 pixels. This will ensure that the image shown is always equal or larger than its container, never smaller. In order to maintain the layout of the grid and never show a pixelated image (i.e. by stretching it), this approach seemed the most reasonable one.

The data-max-width and data-max-height attributes defines the largest image dimension which will restrict it to that size and not stretch it fully in the slideshow view. The slideshow view will take all the window size into account and allow the image to fill up all the possible space. The attributes ensure that the image doesn’t get resized beyond its largest dimension and become pixelated on huge screens.

Some things we are using in Gamma:

There are many things to improve here, it is a very experimental implementation that tries to tackle the responsiveness of a special scenario, an image gallery.

In the demo we don’t really take care of the vertical images which should of course have a set of reasonable dimensions that take the height of common screen sizes into account.

Here are the settings in the Gamma gallery script:

// default value for masonry column count
columns : 4,
// transition properties for the images in ms (transition to/from singleview)
speed : 300,
easing : 'ease',
// if set to true the overlay's opacity will animate (transition to/from singleview)
overlayAnimated : true,
// if true, the navigate next function is called when the image (singleview) is clicked
nextOnClickImage : true,
// circular navigation
circular : true,
// transition settings for the image in the single view.
// These include:
// - adjusting its position and size when the window is resized
// - fading out the image when navigating
svImageTransitionSpeedFade : 300,
svImageTransitionEasingFade : 'ease-in-out',
svImageTransitionSpeedResize : 300,
svImageTransitionEasingResize : 'ease-in-out',
svMarginsVH : {
	vertical : 140,
	horizontal : 120
},
// allow keybord and swipe navigation
keyboard : true,
swipe : true,
// slideshow interval (ms)
interval : 4000,
// if History API is not supported this value will turn false
historyapi : true

And here is an example of how we can initialize the gallery:

<script type="text/javascript">
	
	$(function() {

		var GammaSettings = {
				// order is important!
				viewport : [ {
					width : 1200,
					columns : 5
				}, {
					width : 900,
					columns : 4
				}, {
					width : 500,
					columns : 3
				}, { 
					width : 320,
					columns : 2
				}, { 
					width : 0,
					columns : 2
				} ]
		};

		Gamma.init( GammaSettings );

	});

</script>

The viewport width is the width that we will take into account for choosing the right sized image but also for defining how many columns in our grid layout we want to show. For example, between 320 and 500 pixel we would like to show 2 columns.

The images used in the demo are by Idleformat.

The thumbnail hover style is inspired by the one seen on Nudge.

Feedback, suggestions and comment are very welcome, there is lot’s things to improve and make better. Thank you!

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 132

Comments are closed.
  1. More info: works on IE9 with file protocol but does not work on local serveur or from codrops host.

    • Hi Daniel, there was a conflict with another script in the demo and it’s fixed now! Thanks again for your feedback, cheers, ML

  2. Looks great, but how does it scale images? If a have a bunch of the images with the equal dimensions (say 1000 x 200) how does this grid will display it?

    Thanks.

    • Hi Andrey, the purpose of this gallery is to serve different images for different screen/container sizes. But you can of course use it with just one large version and and a thumbnail size…

  3. I dont know about loading 5 different image size at once for each image. It seems a lot of unnecessary server requests to me.

    • Hi Ozgur, you obviously misunderstood, no 5 images are loaded of course. The whole point of this is to load only the image that is needed… Cheers, ML

  4. as always, great script. And for a play ground, it works quite well.

    And as an FYI: it works very well on OS X 10.5.7 via Chrome, FF and Safari. I also tested on iPad 2 running IOS 5.1.1.

    Beautiful script!

    well done Mary Lou!

    • Outside the fact that isotope would allow/add filtering functionality, can you clarify what other benefits of using isotope would be instead( or your question is in fact asking that)?

    • The only reason would be for the filtering functionality. I might give it a try myself shortly.

  5. You have no idea how useful this post was! Thanks Mary Lou, and the plugin is awesome! Thanks for sharing. =)

  6. That’s amazing !
    I am using Isotope on my website, and always have had this High priority problem with google PageSpeed,
    60% of the image’s data is loaded unnecessarily when viewed on a large width device, since they are shrinked but not scaled to fit the column width. Also, when viewed on a small width device the images are stretched bigger resulting in an ugly pixel rendering.
    The idea of loading different images according to the device width is genious. It saves precious page loading time, which generally is quite long on a gallery website.
    I can’t see any weakness in your code, but I’ll wait a bit before using it on my website, since some people might have interesting improvement feedback to share.
    GJ ML

  7. Hello! Classroom work! is it possible to apply to this script “lazyload” because the script is very good, and posledrvatelnoy-loading pictures available! high output, it is a lot of traffic … Thanks guys!

  8. Wonderful demo, although it rescales a little slow, even in Chrome (but this might be due to its experimental nature).
    One thing I’d personally change is the pixel values for the viewports, instead using em’s. This is much more responsive as it takes zooming and user stylesheets (font sizes) into account.

    Other than that it looks really nice!

    • Hi Reinier, thank you for your feedback! You are absolutely right, em instead of pixel would be a wiser choice, I’ll keep that in mind. Thanks and cheers, ML

  9. Very slick – love the effect of zooming the image out of the thumbnail into the gallery view, Facebook does this in their new iPhone app and it’s really nice. I think some user feedback would be nice while the larger image is being loaded in gallery view (i.e. “enhancing”) just so you know that it’s not a super pixelated image you’re getting.

    Also when you go back to an image you’ve already viewed, the small version is zoomed before you get the full-res version. If this is in cache already, could you expand the high-res version from a compressed size?

    Final little thing is, instead of getting a spinner when you’re clicking to the next image as it’s loaded – if you used an expanded view of the thumb with some “enhancing” feedback I think this would be a smoother experience. Fantastic showcase though, just a few ideas for getting an extra few percent of awesome out of it 🙂

    • Hi Darren,
      excellent suggestions, thanks a lot for you feedback! I agree with all points; I’m not sure if the second one would be a bit heavy because of the zoom effect on a much larger image. Thanks a lot again, it’s great feedback, I really appreciate it! Cheers, ML

  10. Excellent plugin!! Thanks for sharing, love it!

    One Question: Where can i specify how many images are loaded after clicking “Loading more items”?

  11. Slideshow functionality doesn’t work properly.
    If you press “play” , then “pause” , and then continue to via arrows left and right. previous images are not hidden.

  12. Hi Mary Lou,

    Awesome, I love it 🙂 a lot

    Just one hick: it is not responding well on firefox, when clicking on the arrows or close icon.

    Rida

  13. … actually here is the scenario:
    if you try close an image immediately after clicking onto it to zoom it, it doesn’t work. when clicking on the image and then navigating using the arrows and then closing the image after works

    I hope this will help you tracking the issue

    Thanks

    Rida

  14. I love it. Would be perfect if it had the option to share the photo on social networks.

  15. Hi, thank you for this post, love it so much !!!!

    But I have one question, is it possible to make a different link ? let me explain : can I make a link that don’t goes to full size image but goes to another page or something like that ???

    Thank you

  16. Hi,

    Just what I was looking for. Thank you for this great plugin. I am experiencing some issues with it.

    When clicking on the loadmore button, I am loading the next set of images dynamically using Ajax. But when doing so, it shows the titles first and I think it calculates the heights based on this. But later when the actual images are loaded, the height still stays the same. But when I refresh the browser, it loads correctly, possibly because of a cached image. Not sure why this is happening.

    Please have a look at the screen shots which explains the three different behaviours. http://www.bounceapp.com/80715.

    This the call back function, I used to load more images. As this is on my local development server, I cannot provide you a url to have a proper look. But any help on this would be much appreciated.

    Thanks

    John

    function fncallback() { $('#loadmore').show().on('click', function() { ++page; // function that makes a request and returns a promise: function getMoreItems() { return $.ajax({ type: "POST", url: "www.doamin.com/index.php?option=com_rsmediagallery&task=getitems&format=raw", data: { limitstart: $("#gamma-container ul").children().length + parseInt($("#rsmg_original_limitstart").val()), Itemid: $("#rsmg_itemid").val() } }); } // function that expects a promise as an argument: function addMoreItems(ajaxReturned) { ajaxReturned.success(function(data) { var htmlitems = $(''); if(typeof data == "object" && data.items && data.total) { $(data.items).each(function(index, item) { var li = $(""); var divouter = $("", { "data-alt": item.title, "data-description": item.title, "data-max-width": item.absolute_images.maxdata.width, "data-max-height": item.absolute_images.maxdata.height }); var lastimg; $(item.absolute_images.images).each(function(idx, img) { var oneimg = $("", { "data-src": img.image, "data-min-width": img.width }); divouter.append(oneimg); lastimg = img; }); var scrptimg = $("", { "src": lastimg.image, "alt": item.title }); divouter.append($("").append(scrptimg)); li.append(divouter.append()); htmlitems.append(li); }); } Gamma.add($(htmlitems.html())); if($("#gamma-container ul").children().length >= data.total) $("#loadmore").hide(); }); } // get a promise from testAjax: var promise = getMoreItems(); // give a promise to other function: addMoreItems(promise); }); }

    • Not sure.. but it might be that the images chosen to be displayed are not being preloaded. This is something I will have to fix. Thanks for the feedback. ML

  17. Hi many compliments for this gallery but i have a little prob. with chrome mac … in safari and firefox for mac all works good but with chrome there are only 2 columns … and i don’t understand where is the problem … also you page demo in chrome have the same problem …

    look:
    http://www.andromedamurano.it/project/index.html (your page demo)
    http://www.andromedamurano.it/project/index.php (your page demo with my pictures)

    Can you help me please!?
    Thx a lot
    Tommy

  18. Hi Mary Lou,

    Thanks a lot for the reply. I will try something to preload the images. Hope you will update the script very soon 🙂

    Many thanks
    John

    • Hi John,
      have you already found a way to preload the images?
      I’ve the same problem: the images which are appended via ajax are overlapping.
      Thx
      Sarah

  19. Hey Mary Lou, great plugin!
    I’m trying to use it with ajax page loading, and I’ve found that it would be useful to add a reset function to cleanup events and variables, something like

    reset = function(){
    Gamma.singleview = false;

    $window.off( ‘smartresize.gamma’);
    $window.off( ‘statechange.gamma’);
    …..
    }

    ….
    return {
    init : init,
    add : add,
    reset: reset
    }

    if you want to see it live it’s here: http://www.theautumnsrain.com (press and foto)
    Many thanks for sharing this anyway, it’s a wonderful and well well thought plugin!

  20. Hey, I’m messing around with this but I’m a bit confused. Why does it take so incredibly long to load with my implementation? I specifically (and tediously) resided each image to the corresponding sizes which I thought was supposed to keep load times down..Instead it takes like 10 seconds or longer! http://co2oogle.com/portfolio/photo.html

    • Hi Jon, your main container can have a maximum size of 1580px which, with 5 columns set as maximum number and a screen that shows the max width, will load the large image in the thumbnail view instead of the medium one (since the list item will be bigger than 300 pixels). This is what’s causing the high loading time. Either you specify to have another column for larger screens which will make sure the list item will not get bigger than your medium sized images or you add another image size for this case. You could also restrict the main container to have a max-width of 1540px. When I open your page on a large screen I can see what you are talking about, but on a smaller screen it loads pretty fast. So just make sure to tune it appropriately. The ideal approach is of course to have multiple image sizes (our demo is just using a few).
      I hope it helps, let me know how it goes, cheers, ML

  21. Thank you!! This is amazing and just what I have been looking for. Is there a plan to make this into a plug-in for WP? I’d love to use it on my photography site.

  22. This is great! I have one small issue, my previous and next arrows are not showing like they do in the sample. I see that the in the code they aren’t pointing to image files for these icons… any idea how I might get them to show or if I’m missing something?

  23. Hi, sorry for sounding stupid but can I disable the modal window and give a normal href link?
    Thanks

  24. hello,
    Very nice site.
    I tried to do it for my site, it works very well on Dreaweaver, but I put it online it does not work:
    -it does not find the images when they are on the server
    -it does not move from one image to another
    -it does not close the image to return to main page …

    Can you help me?
    http://martinlagardere.com/fashion

  25. Latest version of Chrome shows image in background when set to mobile size and that background image is sticky for some reason.

  26. Hi,

    I’m trying to integrate it in radiant but after I click on a image to zoom in and close it again, I can’t open another image.
    It works fine when I take the code out of the radiant template in a stand alone file.
    The ‘_singleview = function()’ code gets executed each click, but it just doesn’t zoom in the image. Guess the createSingleView function doesn’t get executed because some issue with a selector not matching correctly when the gallery is wrapped up in different div’s.
    Here is the code (site is not yet online): https://gist.github.com/bc8e8d66046d5b209e02

  27. Guys! Please, create a video-mode and comments likes facebook (or block with some content likes fb) in full size image. PLEASE!!
    Fantastic script! Sorry for my bad english 🙂

  28. Hey, I love the idea, love the concept! I have a question: would be possible to do it horizontally? I experience some troubles when I attempt to do horizontal scroll galleries; and the only way I could achieve that, was with way simpler structure, with one or two images, without “adjusting” to the width of the screen… do you think that setting the width of the screen like 10,000 pixels, and moving sideways would make the trick? (I tried that, with another method, but… I totally failed! xd )

  29. Can anyone help me make a minor change to this? Instead of a larger image opening on click, I’d like it to go to a URL. Perfect for our use if I can figure out this one change…

    Steve (srhedd@gmail.com)

  30. Hi Mary,
    this is an awesome script. Thanks for putting it up.

    One Query, would it be possible to open a video hosted on youtube with the light box effect pop up on click of an image?
    Cheers!!

  31. This looks amazing but I cant get it working on a WordPress (WAMP) environment.

    Firebug shows me: “source is undefined, Line 414”
    Line 414 of gamma.js = src : source.src

    When I ignore the error, the image grid shows up, scaling works to but I’m unable to open a fullsize image.
    The page stays black. Only after a refresh (F5) the fullsize image shows up.
    After that, going back to the grid view doesn’t work too.

    Next to the js error, I can see that this part of the HTML is not executed (greyed out in Firebug)

    events=Object { click=[1], swipeleft=[1], mousedown=[1], meer...}handle=function() events=Object { click=[1]}handle=function() events=Object { click=[1]}handle=function() events=Object { click=[1]}handle=function() events=Object { click=[1]}handle=function()

    Any help would be much appreciated! I’m reaching a deadline for a web-project and would love to implement this gallery… 🙂

    Thank you in advance!

    Kind regards,
    Steven

    • My mistake… After loading the gallery scripts in the footer instead of the header, everything works as it should. :-s