Layout Responsive Fluid Columns Using CSS

Damon Bauer
InstructorDamon Bauer

Share this video with your friends

Send Tweet
Published 6 years ago
Updated 4 years ago

Learn how to use CSS columns to quickly lay out fluid columns that are responsive, degrade gracefully and don't require extra markup.


  • column-width operates like min-width, not width. The browser will render as many columns as it can with the width provided. If each column can take up more than the value provided, they will do so.
  • column-span enables a specific element to ignore column-count and column-width. It can be set to an integer to span a certain number of columns, or "all" to span them all. However, this property does not work in Firefox. A workaround could be to move the element (say, a heading) outside of the container with the columns applied to it. That way, it remains outside of the automatic column flow.
  • column-fill allows you to change the way content flows into columns. By default, it's set to "balance", where content is distributed as much as possible between columns. It can also be set to "auto", but in order to do so, it requires setting a fixed height. This breaks the idea of fluid, responsive layouts, so use it with caution. You'll also need some browser prefixes, so be sure to reference this browser support chart.

[00:00] Set up a demo of a footer with a number of links in it, like you might see on a news website. On my nav element, say column-count. This just takes an integer such as 4. When set, it says "Render four columns, no matter the width of the containing element." If I resize my browser, the links remain in four columns, no matter how squooshed or spread out that they become.

[00:22] Next, let's take a look at column width. It takes a length value set in pixels, rems, ems, whatever you'd like. I'm going to set it at 250 pixels.

[00:32] Now when I resize my browser, I've still got four columns, and they're taking up at least 150 pixels. But when I shrink it down and they can no longer take up 150 pixels, it will actually start collapsing the number of columns down so that it can make enough room for them.

[00:50] We can combine these first two properties into a shorthand, columns. I'll comment these out, and now I can just say columns. I want four, 150 pixels. Essentially it says render up to four columns that are at least 150 pixels wide.

[01:08] Another property available is column-gap. Column-gap specifies the gap or gutter between each column and takes a non-negative length, setting pixels, rems, and again, percentages, whatever you'd like. I'm going to set this to 3 rem. I like to think of column-gap as built-in padding between columns without having to do really any math to get the spacing right.

[01:30] Now you'll see that the gap between each column is three rem. That coupled with the minimum width of 150 pixels set before will alter how many columns can fit within the window at a certain time, and will adjust the content of the columns accordingly.

[01:48] Next we can look at column-rule, which allows you to put a border between each column, and it takes the same arguments as border shorthand would, so we could say something like 1 px dashed #ccc, and you'll see that a vertical border was added at the boundary of each column.

[02:08] One nice thing about column-rule is it doesn't render a rule to the left of the first column or to the right of the last column even if I resize my browser. If I resize it down, it's going to drop that last rule. If I resize it up it's going to add an extra one, but it never adds them on the edges, which is really nice.

[02:25] Finally, we can look at a couple of properties with varying browser support. First, column-span. I could say column-span, all. What that's going to do is make the H2 take up all of the column width and force a line break to make all the columns start after it.

[02:44] Finally, let's look at column-fill. By default it's set to balance, which means try to equal out the content between each column. You can change this to auto, which will fill content as much as it can in one column, then flow into the next, and if there's any remaining, it will go into the next, and so on and so forth.