Using CSS3 to Properly Center Thumbnail Galleries

Posted: March 18, 2010 Comments(13)

CSS3 has it’s place. We all may not agree on it quite yet, but it’s there. Some of us think we should just run with the ball, while others just stick with what works. It depends on the project, it depends on the client, and perhaps most importantly: it depends on the target audience.

There are plenty of times in every project where CSS3 would save me time and effort, but I still consistently weigh the benefit and cost to implementing CSS3 on any level in a client project.

In some recent discussion I’ve had with other designers, a question that’s come up relates to which pseudo-selectors I find myself using most often. Pseudo-selectors are awesome. When it comes to a healthy blend of saving time and accounting for the smallest of details in design, it’s hard to find something that packs more of a punch than pseudo-selectors. I say that because the selectors allow you to more easily define a very particular element you’re looking to style. Of course this is already possible using a targeted combination of elements, classes, and ids, but pseudo-selectors let you do things dynamically.

Thumbnail image galleries

Thumbnails listings are awesome. I really like smart designs that incorporate thumbnails because to me it’s the best of both worlds. You’re able to quickly scan a volume of images and easily discern what you’d like to check out first, all the while without a large latency overhead waiting for assets to download. I also like grids. Thumbnail listings are most often a blatant and literal grid so they’re pleasing to my eye.

That said, I’ve engineered the front end of many projects that incorporate thumbnail image galleries, and with a combination of CSS3 and pseudo-selectors, life gets much easier when it comes to implementation. Even if people don’t recognize why, they can tell when something just doesn’t look right. I think it most commonly arises as a result of centering issues; people can most easily tell when something isn’t quite lined up in the middle. While not trivial to spot with a variety of design elements, a grid consisting of square elements is much easier to discern.

Out of the box, you can style a thumbnail gallery with floating list items possessing a certain width/height and specific thumbnail size. What you’ll end up with is an unbalanced group of images:

Visual representation of a thumbnail gallery using minimal markup and style

ul#gallery { overflow:hidden; zoom:1; width:320px; }
ul#gallery li { width:80px; height:90px; float:left; }
ul#gallery li img { display:block; width:50px; height:50px; }

Naturally, everyone has their own way of styling something like this, some will use margins, others padding, we’ll stick with width for this example. The point is, though, that there’s a better way to handle the end result.

Old and busted

We’ve all done it. It very well might be the only time you’ve used the modulus operator in your given server side language. As we’re dumping out the markup for our thumbnails, we’ll tag on either class="first", class="last", and sometimes both if for nothing more than applying a specific style alteration depending on where in the row a thumbnail sits.

Visual representation of a thumbnail gallery using an extra class

ul#gallery { overflow:hidden; zoom:1; width:320px; }
ul#gallery li { width:90px; height:90px; float:left; }
ul#gallery li img { display:block; width:50px; height:50px; }
ul#gallery li.last { width:50px; }

It’s not a terrible solution, but it’s a bit clunky. When we step back and think about it, we’re simply adding these classes for the sake of presentation. While it can be argued that there’s some semantics to it, more often than not it ends up being on a presentational level. Can you truly say that class="last" benefits the document in any way? What happens when the design changes and there are now 5 thumbnails in a row? It’s just one more thing to consider as time goes on.

The new hotness

Pseudo-selectors open the door for elements like thumbnail galleries. With just an additional selector or two you’re able to cut out the extra classes and improve the maintainability of your document all at the same time. The selectors that will be of most use in this case are structural pseudo-selectors. It’s likely that you’ve seen some of these before, but we’ll cover implementation as a replacement for manually adding classes to elements during page load.

What comes in most handy in this situation is the :nth-child pseudo-selector. As defined by the recommendation:

The :nth-child(an+b) pseudo-class notation represents an element that has an+b-1 siblings before it in the document tree, for any positive integer or zero value of n, and has a parent element. For values of a and b greater than zero, this effectively divides the element’s children into groups of a elements (the last group taking the remainder), and selecting the bth element of each group. For example, this allows the selectors to address every other row in a table, and could be used to alternate the color of paragraph text in a cycle of four. The a and b values must be integers (positive, negative, or zero). The index of the first child of an element is 1.

In addition to this, :nth-child() can take ‘odd’ and ‘even’ as arguments instead. ‘odd’ has the same signification as 2n+1, and ‘even’ has the same signification as 2n.

Easy, right? It’s actually not all that bad. What this selector is going to let us do is most closely related to applying a modulus within a loop server side. It’s going to allow the selector to behave arithmetically, which is awesome. In our example, we’re going to use an nth-child selector that will grab every fourth list item and conditionally apply our desired style.

Visual representation of a thumbnail gallery using minimal markup and CSS3

ul#gallery { overflow:hidden; zoom:1; width:320px; }
ul#gallery li { width:90px; height:90px; float:left; }
ul#gallery li img { display:block; width:50px; height:50px; }
ul#gallery li:nth-child(4n) { width:50px; }

So this is the best of both worlds, right? We’re not injecting unnecessary classes conditionally on the server side, and the rendered result is exactly what we’re looking for. Easy peasy!

Back to reality

Unfortunately, CSS3 is a double edged sword, particularly with client work. If you’re at all concerned about pixel (near) perfection in IE, in any shape or form, you can forget about nth-child().

It’s not the end of the world though. Personally, I would proceed in implementing nth-child() in this case. I’m willing to sacrifice the centering of the thumbnails for IE users, because it’s not a disastrous consequence. Combine that with the ease of implementation, and subsequent ease in maintenance and I’m sold.

It’s up to your discretion, though. If you’re willing to accept that it’s an unknown amount of time before the most popular browser on the face of the Earth will render your thumbnail gallery, go for it. This is just the beginning of nth-child(). I truly suggest you check out the recommendation and become familiar with it. There’s tons of stuff you can do with minimal recoil in substandard browsers.

Get my newsletter

Receive periodic updates right in the mail!

  • This field is for validation purposes and should be left unchanged.

Comments

  1. Yes, child selectors are great. But in this example, wouldn’t simply applying a negative margin to ul#gallery achieve the desired effect?

  2. Great point, Leon! I’m glad someone brought it up, but I’m surprised it happened so quickly! To be brutally honest, I’ve never been a huge fan of negative margins. It’s truly a personal preference but the way my brain works I prefer not to have to account for elements overlapping or underlapping one another. I’m not sure if there’s a psychological term for it, but my brain can process the above example slightly easier knowing that elements are contained within one another.

    To answer your question, though, you’re absolutely right!

  3. It’s something I’ve worked on recently, so it rang a bell. I know exactly what you mean: we all do these things in certain ways, and ‘picturing’ a negative margin is difficult (and somewhat counter–intuitive).

    I guess IE9 will support child selectors properly?

  4. Yes, from the looks of it IE9 is going to be a true breath of fresh air! I plan on taking each Platform Preview for big time test drives, but I think our biggest concern will be the actual production date as well as the adoption rate; something we’ve all had to struggle with as each and every version of IE has been released.

  5. Another way to do it which works if you have a wrapper is to set the width you want plus the extra margin on the ul then on a div around the ul you can set the width minus the right margin of the last element and overflow hidden.

    Quite useful and saves any problems with compatibility/templated systems where you have fixed mark-up. Not ideal for everyone.

  6. Also a workable suggestion, thanks Tom! I think a less discussed benefit of CSS3 is that it affords us the ability to not have to be so creative when it comes to (seemingly) simple implementations such as this. As you’ve described, there are numerous ways to solve this ‘problem’ – do you think CSS3 will help standardize the solution?

  7. If you’re already using jQuery then you can use it to support browsers which don’t implement CSS3. jQuery will understand expressions like “li:nth-child(4n)” and allow you to add inline CSS or a class to matched elements. In my opinion this is better than adding meaningless classes or having the layout break in IE.

  8. Leon: I was also thinking of negative margins, and somewhere back in my mind I’m quite sure I have implemented it. However, as I try to reproduce it, it simply won’t work without having an extra container wrapping the gallery. Could you provide us with a working example?

  9. @Jonathan: In my concept, negative margin is used for overlapping layouts and to achieve some desire layout effects. Use for cancel a positive margin seens to me a bad pratice.

Leave a Reply

Your email address will not be published. Required fields are marked *