Thumbnail grid examples
This is a list of examples for the state of the art in HTML thumbnail grids over time. It's self-contained, using only a single external 100×100 image and some CSS.
The goal is a grid of thumbnails that:
- Is easy to author, deploy, reuse, understand, and modify
- Is made of 200×200 cells, with 10px padding and 10px between rows/columns, containing (at least) a thumbnail and a caption on separate lines
- Adjusts sensibly to viewports of arbitrary size
- Does something reasonable when cells are taller than expected, with minimal disruption to the rest of the grid
- Handles incomplete final rows
- Handles leftover space in an aesthetically pleasing manner
- Still looks fine when cells have backgrounds or borders (often the case on hover)
- Ideally, can align cell contents such that the bottom of each thumbnail (and top of each caption) is aligned
The final example is the desired behavior.
Return to the accompanying blog post
1996: Tables
- Worked in 1996.
- Number of columns is baked into the markup, so it doesn't adapt to screen size, either up or down.
- Need to give every cell an explicit width, or the table layout algorithm will make columns different sizes.
- Rather a lot of markup required, especially before CSS could eliminate the repeated
align
andwidth
on every cell. Very little is shared between multiple grids, and keeping them in sync is tedious. - No way to align the tops of the captions, so thumbnails of varying heights look messy.
- Before CSS, border and padding options were limited;
border
adds a border to the entire table AND every cell, andcellpadding
can't set separate horizontal and vertical spacing. - Non-semantic use of tables risks confusing screenreaders and other tools that aren't human eyeballs.
Caption |
Caption |
An especially long and kind of obnoxious caption, used to check edge case behavior |
Caption |
Caption |
Caption |
Caption |
Caption |
Caption |
Caption |
Caption |
1998: Floats
- Much less markup clutter; the entire "grid" is now a single flat (semantically correct) list.
- Cells wrap into rows automatically to fill the viewport.
- Incomplete final rows end neatly.
- Thumbnails must have a fixed height, or smaller thumbnails will "clump up" vertically when trying to float around bigger ones — but this risks overflow, and means rows can't stretch to accomodate an outlier.
- No easy way to distribute extra space; floats can't easily stretch, and centering a block of floats requires some wrapper elements and CSS hacks. You could use percentage widths, but then you have a fixed number of columns again, and spacing becomes more complicated because padding/margin are added to the width.
- Floats don't move the "cursor", so by default they spill out of their container. Need a semi-arcane "clearfix" to get around this.
- No real options for alignment; cells are top-aligned by default, and you're on your own if you want anything else.
- CSS doesn't quite map to what you're trying to do. Margins must be halved, since the gap between cells is the sum of two margins, and they affect the outer edges as well.
- A deliberately-wider cell will simply misalign other cells later in the row, breaking the grid. (Not visible here because images have
max-width: 100%
.)
Caption
Caption
An especially long and kind of obnoxious caption, used to check edge case behavior
Caption
Caption
Caption
Caption
Caption
Caption
Caption
Caption
2008: inline-block
- Finally a semi-intended use of a CSS property, so easier to understand and much less odd behavior to hack around. Relatively simple to implement, understand, and modify.
- Cells wrap into rows automatically to fill the viewport.
- Extra space can be distributed to the sides by centering the entire grid, though this will also center the final row, which might misalign columns.
- Individual "rows" can be taller; however, nothing makes the cells in a row have the same height, so you need a fixed height anyway if you have any backgrounds or borders. A
min-height
could be a reasonable compromise. - No way to align the bottom edges of thumbnails. Only
vertical-align
is available. - Margins still need to be halved and still affect the outer edges.
- A deliberately-wider cell will simply misalign other cells later in the row, breaking the grid. (Not visible here because images have
max-width: 100%
.)
Caption
Caption
An especially long and kind of obnoxious caption, used to check edge case behavior
Caption
Caption
Caption
Caption
Caption
Caption
Caption
Caption
2014: Flexbox
- Simple markup. Simple CSS that (mostly) corresponds to the intended effect.
- Cells wrap into rows automatically to fill the viewport. Handling the perverse case of a very narrow viewport is also much easier.
- Tall items will stretch the row, and other cells in the same row will stretch to match their height (by default; this can be changed).
- Various alignment options are available, including
align-items: baseline
, which does align the bottoms of the thumbnails — though the boxes' edges then don't align. (Not done here; see the grid example below, which does use baseline alignment with much the same effect.) - Several ways to handle extra space: the default is to share it evenly between cells, but it's also possible to keep the cells a fixed width and spread them out in various ways (not done here).
- Spacing between cells can (as of very recently) be specified with
gap
, which doesn't affect the edges and doesn't require halving a margin. - Rows are independent, not part of a grid, so cells of a short final row will be stretched to fill the available width. This can be hacked around by adding a number of dummy zero-height elements to the end of the list (not done here, so the problem is visible).
- A deliberately-wider cell will steal space from other cells in the row, misaligning the faux "grid". (Not visible here because images have
max-width: 100%
.)
Caption
Caption
An especially long and kind of obnoxious caption, used to check edge case behavior
Caption
Caption
Caption
Caption
Caption
Caption
Caption
Caption
2017: Grid
- Simple markup. Simple CSS that corresponds directly to the intended effect. Even the columns are explicitly part of the layout, unlike every other approach thusfar.
- Cells wrap into rows automatically to fill the viewport. Or do any of a zillion other possible things; the layout is extremely flexible.
- Space between cells can be specified with
gap
, doesn't affect the outer edges, and doesn't need to be halved. - Tall or wide cells will only affect the containing row and column, and can't misalign the grid.
- An incomplete final row will stick to the grid, no matter how it's positioned.
- Leftover space can be handled in all the same ways as flexbox: by widening the cells or spacing them out.
- Can align to the bottom of each thumbnail, as seen here, at the cost of the boxes' edges not exactly matching. Can also stretch the cells into a grid, as seen in the flexbox example above.
- Basically perfect. We did it, and it only took 20 years!
Caption
Caption
An especially long and kind of obnoxious caption, used to check edge case behavior
Caption
Caption
Caption
Caption
Caption
Caption
Caption
Caption