Arranging Elements from Top to Bottom instead of Left to Right (float: down?)

Avatar of Chris Coyier
Chris Coyier on (Updated on )

Reader Marcin A wrote in with this question about a simple unordered list in which they wanted the elements to be arranged in vertical order (top to bottom) instead of horizontal (left to right).

So markup like:

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

Which would end up like:

1 4
2 5
3 6

Well Marcin, unfortunately there is no float: down; that you might want here. There are a number of ways, but as you might suspect, there are caveats with all of them.

Absolute positioning

If you know you want the layout exactly like that text diagram and you know the exact width and height of each element, you can absolutely position them in that layout easier. That’s a lot of ifs, but it might be the case if it’s primarily a set of images.

See the Pen gasif by Chris Coyier (@chriscoyier) on CodePen

Noah Blon has an automated Sass-based version to make it easier for an arbitrary number of list items.

See the Pen Vertically oriented list in 2 columns – IE9+ by Noah Blon (@noahblon) on CodePen

Flexbox Columns

Flexbox was made for this kind of thing. You can have the unordered list be a flex container with a column direction, and allow wrapping. Essentially:

ul {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}

In order to match the layout exactly, I’m going to apply a width and height to the flex container. If you don’t have a width, each column will be as wide as it needs to be so that they fill the container. If you don’t have a height, the items won’t wrap.

See the Pen yHoeI by Chris Coyier (@chriscoyier) on CodePen

Reminder you’ll want to mix syntaxes here for the best support.

The advantage here is that the items can be of any size and the behavior will hold. The disadvantage is IE 10+ only.

Text Columns

Another possibility here is making the items inline-block and using CSS3 text columns. Essentially:

ul {
  column-count: 2;
  column-gap: 0;
}
li {
  display: inline-block;
}

Each block will behave just like regular text, it will fill the column vertically before moving over to the next.

See the Pen oFyEH by Chris Coyier (@chriscoyier) on CodePen

Text columns are evenly split across the width of the container, so if you want to be very specific about those column widths you’ll have to be specific about the width of the container.

A difference between this and flexbox is that it will try and split the elements across the columns equally the best it can. So you don’t need to declare a height if you don’t want to. Essentially it tries to make it as short as possible.

Bring your own prefixes, and also IE 10+ again.

Got another way?

Let’s hear it! CSS is fun. Maybe grid layout in the future?