Responsive gallery tiles with pure CSS

Airship
Airship
Jul 22, 2017 · 6 min read

Hello world! I’m not very familiar with blogging nor Medium, so… Sorry if it’s hard to read or something :)

When I joined SoFurry-Next team last spring, I noticed they had an old problem with gallery view. The problem was with creation of perfectly aligned tiles for gallery views, including text posts. Masonry JS? Otherthingy JS? Yes, but they weren’t the perfect solution at all, since we want to avoid JS as much as possible. When I told I could try to make it with pure CSS, no one believed me. Challenge accepted!

Final result

I knew how to make Pinterest-like tiles with CSS float for a long time, but this approach isn’t good for this task, since we want horizontal rows, not vertical. For the last years I was having fun with CSS flexbox, slightly abusing it for one big game company web project. So my solution was flexbox grid.

Here’s a great flexbox reference:

Please note, that I expect reader to be familiar with CSS and other wizardry :)

JSFiddle result can be found at the end of this post.

Task requirements

  • Tiles could be image or text (HTML).
  • Both tiles should include text title and must be clickable.
  • Cosmetics: tiles should be zoomable on hover.
  • Size of tiles’ source is unknown (sic).
  • Tiles must fill all of the available space in a container, depending on their content.
  • Container could be resized.
  • No JS if possible (Spoiler: possible!)
  • Cross-platform (I used IE11 during development, so other browsers work fine with the result)

Let’s start

We start with a typical HTML5 code with some JS as a content generator. JS isn’t required, but it’s eases the template modifications. On a final website for this task HTML gets generated with PHP (which isn’t my job).

What we get here is HTML with some sample content. Templates in this example:

For reference, classes are:

  • .thumbs for the container
  • Shared .thumb class for items
  • Individual .thumb-img and .thumb-txt classes for image and text tiles

Item’s parent is <a>, which isn’t really correct use of anchor, but hey, it works well for no-js solution. Inside of it we see <div> with text title and subtext/content <span>s, and <img> for image tile (we’ll get back to this one later).

CSS

Of course, it will be CSS3. So let’s start with container.

Container’s job is to keep everything stretched in rows inside it.

Shared tile rules:

To keep everything perfectly aligned in one row, we should not forget to specify height.

Hover, transition, transform and z-index here are for zoom. Z-index is vital to keep zoomed tiles above their neighbors. Don’t forget to specify z-index in both rules or this won’t work in all browsers!

Transition for background-position is only used for image tiles, we’ll get back to this later.

Limit min and max sizes for tiles. They can be separate, but for a demo let’s make them the same.

Remember that we have requirement of tile size by its content, BUT they should cover the whole row? That’s exactly why we have to set the sizes for inside elements — to allow them to overstretch.

Image tile:

We have image template with background-image set in embed style for the parent element, and that’s why:

  • <img> element is used only to set the base tile size and proportions, not to be visible!
  • Parent’s background-image is what we will show in a tile. But to be sure if it is shown on the whole tile’s space, we should sacrifice some of it’s height. In other words, when the tile width becomes bigger than width by its content’s proportions, the image inside it becomes stretched by width forcing vertical image parts off screen. This can’t be solved in other way, so we will deal with it using:
  • :hover and keyframes. They are used to scroll the image up and down to show the whole picture. And that’s where .thumbs transition background-position is used. Easy, huh?
Notice the correct zooming overlap — z-index is in the game!

Then we add text styles. They are used both for image and text tiles.

And the rest of the text styles, including small part for text tile:

To avoid lone items stretching for the whole row (could happen with the last row), add this rule:

This will add blank space at the end, which will appear only if needed. Alas, this may not work in IE :(

That’s all, folks!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade