How to Build a Responsive Thumbnail Gallery

by on 3rd January 2012 with 38 Comments


Recently I set out to build a responsive thumbnail gallery. I expected it to take me a few minutes, but in reality it took me a few hours to work through. We’ll walk through a similar process today to help you get your mind wrapped around how it works.

One major component of mastering responsive design is to figure out how to approach specific tasks and adjust to problems as they arise within the context of larger projects. One day you’ll be working on a project and will need a responsive gallery and you’ll remember this post on that very topic.

Sneak Peek

Before we get started, take a quick look at what we’re building. Be sure to resize your browser window page to get a glimpse of just how well the page responds to different viewport sizes.

Demo: Click here to launch the demo.


Initial HTML

Let’s jump into this project with some basic HTML. Instead of using plain old images in our gallery, we’ll go for something that’s much more versatile. For any given entry, you might want an image, title and brief description. Wrap all of this into a repeatable element and throw it all into a container div. It should look something like this:


Lorem ipsum dolor sit amet...


Lorem ipsum dolor sit amet...

To add items to the gallery, simply copy and paste the galleryItem div (our example will use ten of these). From here we can see what we’ll need to target in our CSS. We have two classes: container and galleryItem. We also have some images, h3 tags and paragraphs. For the images, I’ll be using photos from LoremPixel.

Container Styles

To begin our CSS, let’s set a width to the container and center it on the page. This gives us a nice, wide area to work in for our gallery.

.container {
	width: 80%;
	margin: 30px auto;
	overflow: hidden;

Notice that I’ve set the width with a percent. This how we make sure the whole page is nice and fluid. We don’t want the design to merely look good for a few preset breakpoints, instead we to make sure that it can continually adapt to whatever viewport is being used.

Basic Gallery Styles

Now let’s attack the galleryItem class basic styles. We’ll set the text color and font-size and float the items to the left.

.galleryItem {
	color: #797478;
	font: 10px/1.5 Verdana, Helvetica, sans-serif;
	float: left;

.galleryItem h3 {
	text-transform: uppercase;

.galleryItem img {
	max-width: 100%;
	-webkit-border-radius: 5px;
	-moz-border-radius: 5px;
	border-radius: 5px;

I also added some image styling here. By setting the max-width of the images to 100%, I’ve ensured that, as the page gets narrower, the images will follow suit. I finished off by slightly rounding off the corner of each image.

We’ll add the column widths in the next step but for now I wanted to give you a preview of what the text and image styles will look like once we get all that worked out. If you’re following along, you should only have on wide column at this point but your text should look like this:


Flowing the Columns

This is the trickiest part. We need to figure out our width and margin for each of the elements in the gallery. As with the container as a whole, each of these will need to use a percentage so they adapt to changes in the viewport size.

As a starting point, I’d like to use a five column design. To figure out the math necessary to pull this off, it’s easiest to start with the margins. I want a four percent margin between each column, so multiply that by five columns and we know that twenty percent of our width will be eaten up by margins, which leaves eighty percent for content. Eighty percent divided by five equals a sixteen percent width for each column.


Now we can add these values to the CSS that we’ve already established. Each .galleryItem class represents one column, so each will have a width of 16% and a margin of 2% on each side for a combined total of 4% per item.

.galleryItem {
	color: #797478;
	font: 10px/1.5 Verdana, Helvetica, sans-serif;
	float: left;	
	width: 16%;
	margin:  2% 2% 50px 2%;	

This gives us a perfect five column layout that looks great on screens that are 13-inches or larger.


Where It Gets Ugly

Unfortunately, this layout really starts to suck as we reduce out page size. By the time we’re under 500px wide it has completely lost its readability and usefulness.


To address this problem, we’ll use media queries to insert some breakpoints that will reflow the columns to a more appropriate size.

Deciding On Breakpoints

There’s been a lot of discussion lately on which breakpoints you should aim for in your design. The market is saturated with different devices all at different sizes, and it’s not easy to account for all of these specifically.

To simplify this task, let’s scrap our thoughts about what size screen the most popular devices have and let our design itself decide where the breakpoints are. If we analyze the points where our layout breaks down, we can fix those specific areas, thereby making our design look good on every conceivable device (our fluid grid takes care of the in-between).

Where Does It Break?

The best way to test this is just to open our live preview in a browser and start reducing the window size. Technically, our layout will never break because it’s built to scale. However, at around 940px, the columns of text start to become far too narrow for my liking:


To account for this, I need to bring the column count down to four instead of five at that point. By reducing our column width to 21%, we can do this very thing. Since I’m using both “max-width” and “max-device-width” here, the design will reflow on both desktop browser windows (at this size and lower) as well as any devices with physical screen sizes under this width.

@media only screen and (max-width : 940px),
only screen and (max-device-width : 940px){
	.galleryItem {width: 21%;}

Adding in these styles fixes this problem up nicely. Our five column design now works perfectly from full size down to 940px, at which point it turns into a four column design.


Lather, Rinse and Repeat

At this point, you just repeat this same process over and over. Keep reducing the window size and watching for a point where the design no longer functions well. I quickly find another problematic area around 720px:


This time we want to bring the design down to a two column design, which is done with a column width of around 29.33%.

@media only screen and (max-width : 720px),
only screen and (max-device-width : 720px){
	.galleryItem {width: 29.33333%;}


I continued this process all the way down the the point where I only had one column right around the size of the iPhone. Here’s the full set of media queries.

@media only screen and (max-width : 940px),
only screen and (max-device-width : 940px){
	.galleryItem {width: 21%;}

@media only screen and (max-width : 720px),
only screen and (max-device-width : 720px){
	.galleryItem {width: 29.33333%;}

@media only screen and (max-width : 530px),
only screen and (max-device-width : 530px){
	.galleryItem {width: 46%;}

@media only screen and (max-width : 320px),
only screen and (max-device-width : 320px){
	.galleryItem {width: 96%;}
	.galleryItem img {width: 96%;}
	.galleryItem h3 {font-size: 18px;}
	.galleryItem p, {font-size: 18px;}


There we have it. You should now have a nicely formatted responsive thumbnail gallery that looks great on just about every device and browser window size.

Instead of thinking about which media queries are the most popular, we instead analyzed the points where our specific design ceased being functional and reduced the number of columns at that point to make for a better reading experience. The result is a design that excels in the in-between.

Comments & Discussion


  • Jen

    Fantastic article. Many thanks

  • Jeffrey Way

    Nice one, dude!

  • Char

    I really enjoy these tutorials. They are both informative AND inspiring! Two birds with one stone :)

  • a5his

    Nice and impressive !!

  • Jason Gross

    I would consider it worth noting that the use of your ‘galleryItem’ div’s is the perfect opportunity to implement instead for those looking to take the HTML5 approach with a project like this.

    It’s good to see the exercise of building media queries around the content instead of trying to fit your thumbnail gallery around the default sizes of popular devices. Too many people get caught up in the practice of ‘how will this look on an iPhone!?’ when this method of building breakpoints around the content will solve the problem for your iPhone and every device in between.

    I would say that starting with the smallest screen size and working your way out (mobile-first) using min-width instead of max-width in your queries will make loading your CSS a little more mobile friendly. This way you send a minimal amount of CSS to small devices and the full stack to widescreen mediums.

    Regardless of these differences in execution the result is great and has a wonderful flow to it.

  • Zamani Peters

    This is one of the best articles written on responsive web design that I have read. I wish this article was written earlier. While working on a large Classifieds project, I struggle for a few hours trying to implement such a gallery and ended up using this exact approach. I am very pleased with the final outcome.

  • Chris Firth

    Excellent article, a much better way of deciding break points for your Media Queries

  • Dustin

    Very well written and helpful article. Thanks.

  • Joshua Johnson

    Thanks guys! I really appreciate the comments. Jason, you definitely make some solid points about the mobile first movement, it has some good logic behind it and I’ll be exploring that method for future projects.

  • Brent Galloway

    I was cleaning up my portfolio site last week and I could’ve used this post! I figured it out, but wish I had this last week :P Awesome post. It was very helpful, thanks!

  • Brent Galloway

    I was cleaning up my portfolio site last week and I could’ve used this post! I figured it out, but wish I had this last week :P Awesome post. It was very helpful, thanks!

  • Matt

    The demo gallery isn’t responsive in my Android’s browser (HTC Incredible – latest OS).

  • Raghavener

    Nice article… for more semantic and tags should be used…

  • Raghavender

    figure and figcaption tags should be used for better semantic

  • Stéphanie

    ” Instead of thinking about which media queries are the most popular, we instead analyzed the points where our specific design ceased being functional ” => Excellent point, I came across the same conclusion two days ago while creating a WordPress responsive template, so I end up with media queries that are not device spefic

    For the images responsive,you could add height:auto, so that the images will scale nicely. See full image responsive reset code here :

  • Alessandro

    Great article, it could also be used as a starting point to build responsive web pages….

  • sovit Ranjitkar

    Great Article. Learned a % calculation for responsive column gallery. Thnks a lot for sharing Keep sharing Joshua Johnson U Rocks !

  • JG

    Thanks for the great tutorial. It doesn’t seem to work with opera web browser. Does anyone now why this would be?

  • Ryo


    Nice tutorial:)

    I found a bug :

    If the paragraphs of the first image line have not the same length (or the same number of words if you prefer, the first one takes 1 line, the next two lines, the third one line,… for example), the images of the second image line have a strange behavior, they are shifted.

    How can we fix this ?

  • Ryo

    I forgot to see the bug please desactivate the media queries:)

  • robotcom
  • robotcom

    Photo number six — line 61 — is missing the beginning anchor tag. This makes the demo break between the sixth and seventh image when minimized. Otherwise, a great piece.

  • Prodyot

    Crisp and “no nonsense” approach.
    Thanks for the tutorial.

  • Erin

    Hey, thanks so much for the post. I’ve been trying this out and it doesn’t seem to work correctly when the text is different amounts for each line? Is there some sort of clear I’m missing?

  • Chris Loosley

    This looks like a useful method and nicely written tutorial. However, I tried the demo page and (on a laptop with Windows XP) it only works in Chrome. It does not work at all in IE, and works only partially in Firefox — resizing eventually forces the items into three rows, but only the left halves of items 4 and 8 are visible in the window. I do not have Safari installed at present.

    Are there known issues with some browsers?

  • Bennett McElwee

    This doesn’t seem to work on my Android phone:

    It’s a SE Xperia Ray running Android 2.3 (I think). Perhaps because it has a hi-res screen (like the iPhone’s retina display).

    But anyway, I feel you have glossed over the issue of link targets. This is where we doreally need to know more than the screen size — we need to know whether the users has a mouse or touch interface, but most responsive designs just try to guess this by looking at the screen size. It’s not a good solution.

    The problem is that media queries are only about display capabilities, not input capabilities. We need media queries like @media touch and @media pointer to deal with this.

  • Erin

    As a follow up to my own question about varying content heights, I ended up formatting the images and text using and to place the content. Then used the following css on the : {display: inline-block; vertical-align: top; width: 16%; margin: 2%;} and completely removed the floats all together. Works like a charm!

  • SelenIT

    Joshua, can you please explain why are the ‘max-width’ media queries in the example duplicated with the ‘max-device-width’ of the same value? Is ‘max-width’ not always smaller or equal than ‘max-device-width’? Why is ‘max-width’ alone not sufficient?

  • Tobias Wagner

    Great article, Joshua! I really like your concept of “where it gets ugly” and not just taking some fixed dimensions of different devices – like most do :)
    Again, thank you for this great article!

  • Alexandr

    Try to insert more text in one of ‘s and you’ll see how grid become broken.

  • http://none Citlalli

    hello, i am creating my first page on omega, How do i use it in media queries, if omega has created for them?? i am confused for that.

  • Arie Putranto

    I couldn’t agree more. Yes, indeed. Targeting specific device will be good for one who has a lifetime for one single design. For me, fluid will be enough, and set some break point in general could work …

  • Jo

    Thanks Erin!

  • jukooz

    Great article, thank you. How would you do a Responsive Menu similar to this with image (thumbnail) background for each menu item (for each the same)? It seems to me its impossible to do with background-image css property (elements can’t scale to their background images).

  • Didier

    I’m late in the game and this is the best advice on responsive design I’ve read thus far. Well done.

  • Ulsen


    To all of you who got problems with the different heights occurring because of different caption lengths:

    You need to write a JavaScript that reads/calculates the height of the highest div with the class “galleryItem” and sets this height for all of these divs. Or you set a fixed height using CSS.

    Block elements (e.g. divs) are by default only as high as their content.


    That is very fascinating, You are an overly skilled blogger.
    I have joined your rss feed and look forward to in search of extra of
    your fantastic post. Additionally, I have shared
    your website in my social networks

  • Hares

    This is a very helpful article please keep it up.


About the Author