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?
Absolutely nice!
but what about doing this with elements of a table? it would be great.
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
The flexbox option needs a vendor prefix for work on Firefox or simply ffx doesn’t support that syntax?
Yeah, I don’t see any wrapping in FF as well.
Firefox does not support flex-wrap yet. You can follow the progress here: https://bugzilla.mozilla.org/show_bug.cgi?id=702508
Good to know. And also good to know that it will probably be supported this year (see last 3 comments on the bug)
^ That should have been http://codepen.io/anon/pen/CnIJe
I really like this solution. It’s clean and simple… and no support problems
maybe i don’t get problem, but…
aaah, sorry, remove my 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/twrCGJust about every browser should still render that fine though.
You can use CSS Columns. See my example here: http://codepen.io/anon/pen/tgcow
Yeah man! I totally have that in the article as well.
Here it is with simple floats and not much trickery.
(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.)
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.
There may well be a float: bottom. If the books and figures CSS specs go through (http://blog.whatwg.org/css-books-css-figures).
Maybe with some extra markup?
Oh, unordered list… my fault :)
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!
Using a mix of float and inline-block elements can make the deal:
http://codepen.io/nobuti/pen/kuEio
I didn’t know about the ~ selector – very handy!
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.
The simplest, the ugliest, but works :)
Just use float: right and make it LOOKS like float: bottom.
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.
strike that webkit bug thing. my bad.. this behviour only occurs if you give the items a width, which Chris did warn about.
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)
Really useful tip! Thanks to share
However I do not like flex propery too much becouse it has low performance on mobile..
Depending on the needs, one could use
position: relative;
and then:nth-child()
withtop: items-compiled-height-px;
andleft: items-width-px
.Codepen Link
I do think that this should semantically be an ordered list, right?