An adventure in CSS with column lists

css design 2 comments suggest edit

Sit back and relax as I regale you with a harrowing account of trying to do something straightforward with CSS. Ha! Straightforward. How silly was I to think that. As they say,

Fool me once. Shame on you. Fool me twice, CSS.

To give credit where credit is due, my blog has a contributors page. This page lists the folks who have submitted a pull request to my blog with corrections such as typo and spelling fixes. Lots and lots of fixes. Because I make a lot of mistakes.

The first version of this page was a simple bulleted unordered list. It was fugly.

What I wanted to accomplish was something more like this.

The end goal - list of contributors in columns

And if you resize the browser to be more narrow, I wanted the list to collapse to fewer columns.

Four columns

Turns out, this is easier said than done.

The Setup

First, let’s look at my initial conditions. I have an unordered list of images and names from the original 1972 members of Earth Wind & Fire, who have contributed a lot to music.

<ul>
  <li><img src="…"/><a href="…">Maurice</a></li>
  <li><img src="…"/><a href="…">Verdine</a></li>
  <li><img src="…"/><a href="…">Don</a></li>
  <li><img src="…"/><a href="…">Philip</a></li>
  <li><img src="…"/><a href="…">Roland</a></li>
  <li><img src="…"/><a href="…">Jessica</a></li>
  <li><img src="…"/><a href="…">Larry</a></li>
  <li><img src="…"/><a href="…">Ralph</a></li>
</ul>

Without any styling, it’ll look like more or less like this.

Ugly list

It evokes a Mosaic-era design. This is what my contributors page used to look like.

The column-count css attribute allows you to specify the number of columns. To keep things simple, I’ll focus on Chrome and ignore the vendor specific prefixes until the end.

I’ll also add the column-rule attribute so we can see where the columns begin and end. And lets get rid of the bullet points with list-style-type.

ul {
  column-count: 4;
  column-rule: dotted 1px #333;
  list-style-type: none;
}

This results in:

Four column layout

Ok, not too bad. To put the name on its own line, we’ll set it to be a block display. We’ll also center everything in each list item.

ul {
  column-count: 4;
  column-rule: dotted 1px #333;
  list-style-type: none;
}

li {
    text-align: center;
}

a {
    display: block;
}

Four columns, each centered

Wow, that worked just fine. I seem to be on a roll. You would be forgiven if you think we’re close to being done here. But remember…

THIS... IS... CSS!!!

Let’s make sure this continues to work as we add more band members. Fortunately with Earth Wind & Fire, there are many to choose from.

Still four columns, but why is the third longer

Well that’s unexpected. Notice how Larry’s name is in the next column. It seems that the columnization factors in each image and anchor element. But if that’s so, it’s unclear why the first two columns have four elements and the last two have five.

Let’s add one more list item.

Shit's gone bonkers

WTF CSS?!

I thought maybe if I applied break-inside: avoid; to the list item, it would fix things, but that would make too much sense, so it doesn’t work.

Instead, I found this StackOverflow answer that notes display: inline-block; is necessary. But it turned out that wasn’t enough. I also need to set the width of the list items to 100%.

li {
  text-align: center;
  display: inline-block;
  width: 100%
}

Looks better

Much better. Let’s see what happens if I add one more element.

That loks great

Now it looks great! So as the list grows, there’s a few intermediate stages where things look off, but overall it works.

Let’s polish it up. I’ll also add in the vendor specific prefixes. I’m going to remove the column rule because NO PARENTS, NO RULES!

ul {
  -webkit-column-count: 4;
     -moz-column-count: 4;
          column-count: 4;
       list-style-type: none;
}

li {
  text-align: center;
  display: inline-block;
  width: 100%;
  padding-bottom: 20px;
}

a {
  display: block;
  font-size: 0.9em;
  text-decoration: none;
  font-family: "Open Sans", helvetica, arial, sans-serif;
}

img {
  width: 64px;
  -webkit-border-radius: 50%;
     -moz-border-radius: 50%;
          border-radius: 50%;
}

Just like my blog

And that’s pretty close to how it looks on my blog.

Rethink the assumptions

In the end, I realized I was going about this all wrong. One benefit of the column approach is the column rule. If you can’t change the market, that perfectly spaced rule is difficult with unordered list.

But as I mentioned before, I don’t care about the rules. I also don’t care about how many columns the images are in. I just care that they are aligned and responsive to size changes.

So I can get rid of the column stuff on the list and set a specific width for each list item, I can get a nice columnar layout (the styles for anchor and image are unchanged).

ul {
  list-style-type: none;
}

ul:after {
  content: '';
  width 100%;
  display: inline-block;
}

li {
  text-align: center;
  display: inline-block;
  padding-bottom: 20px;
  width: 200px;
}

Notice that there’s a weird ul:after hack in there. That’s to ensure there’s always an extra line, otherwise the very last line won’t be justified. I found that trick here.

Nice columnar layout

And look how it responds when I narrow the window.

Three column layout

Even better, this approach lists contributors in a more natural order for those of us who read left to right.

An even better approach

And of course, not long after I posted the original version of this post, two commenters mention two better approaches, CSS Flexbox and CSS Grid.

This is why I’m happy to put my CSS ignorance on display to the world - people with more knowledge than me provide better solutions than the ones I came up with.

I ended up using CSS grid because the second commenter, Jonathan, provided the exact CSS I needed and it worked. This meant I could simplify the CSS.

ul {
  list-style-type: none;
  display: grid;
  grid-template-columns: repeat(auto-fit,minmax(132px, 1fr)); 
}

li {
  text-align: center;
  padding-bottom: 20px;
}

No changes to the image or anchor CSS were needed.

Listing contributors

You might wonder how am I listing contributors to my blog? Am I editing a list every time I merge a pull request? Ha! I’m too lazy for that.

Fortunately, GitHub Pages provides access to GitHub data for your hosted Jekyll-based site.

I wrote a detailed post a while ago with a nice demo site that explains how to do this. So feel free to give your contributors a shout out with all the columns you need.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

2 responses

  1. Avatar for Mike Simpson
    Mike Simpson December 3rd, 2018

    Umm… I’m not a CSS expert either, but I think flexbox (https://css-tricks.com/snippets/css/a-guide-to-flexbox/) can do this for you pretty easily.

  2. Avatar for Jonathan
    Jonathan December 3rd, 2018

    CSS grid layout is what you want:

    ul { display: grid;
    grid-template-columns: repeat(auto-fit,minmax(64px, 1fr)); }