Categories
Uncategorised

CSS Columns simplified

I’ve been taking a deep dive into next-generation CSS layout modules over recent months, specifically Flexbox and CSS Grid. These layout modules are fabulous, but they don’t deal very well with the idea of text flow when it comes to multi-column layouts. If you check out my course pages, I use unordered (bulleted) lists to display a list of topics. The lists are fairly long (around 30 items), and don’t look good on wider screens when rendered as a single column. I’m using CSS Multi-column Layout (or CSS Columns for short) to automatically split the topics list into 2 columns. CSS columns lets you autoflow text across multiple columns, just like you would in page layout software like Adobe inDesign.

The topic list displays as a single column on smaller screens, and as a 2-column layout on larger screens. I’m using a single list for this. There are no column breaks and the number of list items per column is determined by the browser. I’m using a media query to ‘turn on’ the columns for larger screens.

Sample HTML

<ul class="topic-list">
    <li>How flexbox works.</li>
    <li>Setting flex direction.</li>
    <li>Equal and variable width columns.</li>
    ...
</ul>

CSS

@media (min-width: 640px) {
 .topic-list {
    column-count: 2;
    column-gap: 2em;
  }

  .auto-columns li {
    break-inside: avoid;
  }
}

Let’s break that down:

As I just want to display 2 columns and am not concerned with their exact width, I only need to specify the number of columns. The browser will figure out how much space is available and allocate it equally to both columns.

Column-gap is fairly self-explanatory, providing a gutter between the columns. No need for margins or padding. The column-gap property is now implemented in Flexbox and CSS Grid, replacing the grid-gap property.

I’m using break-inside:avoid on the list items inside the unordered list, as I don’t want these to span across 2 columns.

That’s it! A simple way to deal with long lists without having to manually split content across multiple containers.

Browser prefixing

At the time of writing, CSS Multi-column Layout is not fully supported across modern browsers (particularly the break-inside property), so you’ll need to prefix your code (I use Autoprefixer to handle this). don’t forget to check out caniuse.com for the latest levels of browser support.

@media (min-width: 640px) {
 .topic-list {
     -webkit-column-count: 2;
     -moz-column-count: 2;
     column-count: 2;
     -webkit-column-gap: 2em;
     -moz-column-gap: 2em;
     column-gap: 2em;
   }

.topic-list li {
    -webkit-column-break-inside: avoid;
     -moz-column-break-inside: avoid;
     break-inside: avoid; 
   }
}