Grow your CSS skills. Land your dream job.

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

Published by Chris Coyier

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?

Comments

  1. Permalink to comment#

    Absolutely nice!
    but what about doing this with elements of a table? it would be great.

  2. Dan Woodroffe
    Permalink to comment#

    http://cdpn.io/yHoeI would work for ie9+ but you’d need to know the number of items and not sure how this would play with unknown widths

  3. Permalink to comment#

    The flexbox option needs a vendor prefix for work on Firefox or simply ffx doesn’t support that syntax?

  4. Dan Woodroffe
    Permalink to comment#

    ^ That should have been http://codepen.io/anon/pen/CnIJe

    • Max

      I really like this solution. It’s clean and simple… and no support problems

  5. tamas
    Permalink to comment#

    maybe i don’t get problem, but…

  6. Permalink to comment#

    This would be the easy option… if <div> inside <ul> was valid HTML (no reason why it shouldn’t be IMO, but it isn’t): http://codepen.io/stucox/pen/twrCG

    Just about every browser should still render that fine though.

  7. Permalink to comment#

    You can use CSS Columns. See my example here: http://codepen.io/anon/pen/tgcow

    • (For this solution, you only need to know the widths in certain cases. If your list content is simple text, the content of 3/4/5 will flow around the floated 1/2/3 without any need for the width-specific margins.)

    • Kurt
      Permalink to comment#

      How would this be done with a 3 columns? Would the ‘clear’ mess that up?

    • Yeah, the clear makes this approach only work with 2 columns. It only works because the 2nd column isn’t actually floated.

  8. Ashley Wright
    Permalink to comment#

    There may well be a float: bottom. If the books and figures CSS specs go through (http://blog.whatwg.org/css-books-css-figures).

  9. Benny
    Permalink to comment#

    Maybe with some extra markup?

  10. Have you ever thought about adding a little bit more
    than just your articles? I mean, what you say is important
    and everything. Nevertheless imagine if you added some great pictures or video
    clips to give your posts more, “pop”! Your content is excellent but with
    images and videos, this website could definitely
    be one of the very best in its field. Great blog!

  11. Permalink to comment#

    Using a mix of float and inline-block elements can make the deal:
    http://codepen.io/nobuti/pen/kuEio

    • Dan Woodroffe
      Permalink to comment#

      I didn’t know about the ~ selector – very handy!

  12. Dan Woodroffe
    Permalink to comment#

    Thought I’d add this a bit more cleanly, with a bit of explanation.

    Assumptions:

    1 – You know how many list items are in the collection, personally i’d apply a class on the server side to the midway point for dynamic list sizes

    2 – You know the dimensions of list items, or are willing to use border-collapse or no borders to enable %age based positioning

    3 – You don’t need to support ie8 (or have a polyfill for nth-child)

    With these aspects covered, you can use nth-child(4) to target (in the case of 6 items) the first-after-midway item and pull it up out of the flow with a neg top margin, subsequent items will flow with this. you can then use nth-child(n+4) to target the first-after-midway and subsequent items and add a left margin.

  13. Eryk Piast
    Permalink to comment#

    The simplest, the ugliest, but works :)

    Just use float: right and make it LOOKS like float: bottom.

  14. Permalink to comment#

    Similar to AP ( but w/o taking elements out of the flow) you could use margins to position elements. like this:

    I would like the text column take, as a viable alternative to flex box. Tho, one should note that, in Webkit , if your item heights aren’t all equal the you get and odd sort of space at the bottom of all columns, even the tallest one ( which is odd); I am guessing this is the usual webkit white space bug at work.

    • Permalink to comment#

      strike that webkit bug thing. my bad.. this behviour only occurs if you give the items a width, which Chris did warn about.

  15. OK I’ve been lurking for awhile and this is my first post, so please be nice even if this needs a hack for IE.

    The css is really simple and it is symantic for anyone using a modern browser.

    If not – well then you get what you deserve.

    Use an enclosing div with a column-count, then conditional comments for IE to turn it into individual lists floated left.

    Like here: http://fastexas.org/honors/district.php

    or this codepen: http://codepen.io/RioBrewster/pen/CafsF

    (You need this in the ieHacks.css file. CodePen doesn’t seem to ignore this in the conditional)

    .threecolumn {
        width: 200px;
        float: left;
        margin-left: 10px;}
    
    .threeColcss{
        width: 100%;}
    
  16. giacomo upCreative
    Permalink to comment#

    Really useful tip! Thanks to share

    • giacomo upCreative
      Permalink to comment#

      However I do not like flex propery too much becouse it has low performance on mobile..

  17. ElijaFowler
    Permalink to comment#

    Depending on the needs, one could use position: relative; and then :nth-child() with top: items-compiled-height-px; and left: items-width-px.

    Codepen Link

  18. Adam Michael Garrett
    Permalink to comment#

    I do think that this should semantically be an ordered list, right?

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".