How to display a list in two rows?
Asked Answered
T

8

30

I have a list of items that I want to fit in a space that is constrained vertically:

<ul>
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
    <li>Four</li>
    <li>Five</li>
    <li>Six</li>
</ul>

Since I don't want the list to have more than a specific height, but I'm free to expan it horizontally, I want to divide the list into columns, like this:

One    Two     Three
Four   Five    Six

Or, alternatively (in my case order is not important)

One    Three   Five
Two    Four    Six

The css property column-count allows to break a list into columns, but it only accepts a fixed number of columns. I don't know the number of items I am going to have (it can go from 1 to more than 40), so if I set the number of columns to 3, any list with more than 6 items will be too high, and if there is only 4 items, then only the first column will have two items and it will look uneven.

So, ideally I would need a row-count property, but it doesn't exist. I guess I can do that in Javascript too but I'm looking for a CSS-only solution.

I tried something: float:left on every li puts the list in one row. To break it into two rows, I would need to not apply float:left to the N/2 element. I don't know how to do that.

I know also that I can do it by breaking it into multiple ul, each one with two li, and float:left them, but I would like to avoid messing the HTML for something entirely presentational.

Does someone has a solution for this problem?

Edit: I think I have not been clear in explaining my requirements. I want the list to be sorted into columns without knowing how many items I'm going to have, and so that I will always have two rows.

So for example with 7 items, I want to have:

One    Two     Three   Four
Five   Six     Seven

And with 3 items:

One    Two
Three  
Tefillin answered 13/12, 2013 at 15:41 Comment(7)
@JoshPowell: I discussed that: I don't know the number of items I am going to have, so column-count will make me have more than two rows if there are 7 items or more.Tefillin
Ahh I see I see, so you want a endless amount of rows to best fit the content, right?Fiorenza
See my edit: I always want two rows, and as many columns as necessary.Tefillin
Hmm, I'll try some ideas out.Fiorenza
This can't be done in CSS; you need javascript. But it's a good question so upvoted. You need the right tool for the job.Albi
Well, if it can't be done in CSS, I'm going to accept the Javascript answer, of course. (I still let people some more time to give alternative answers if they want)Tefillin
@Albi For sure it can be done with CSS see hereGrecian
T
18

Here is a simple way to do it using jquery. I know it is mentioned that a CSS way is needed, but this is just for future reference if anyone wants to refer to this question.

Get the number of LI items and divide it by the number of rows and set that value to column-count property.

Jquery

$(document).ready(function() {
var numitems =  $("#myList li").length;

$("ul#myList").css("column-count",Math.round(numitems/2));
});

CSS

ul {
  width: 900px;
}
li {
width: 75px;
height: 75px;
margin-top: 10px;
margin-right: 10px;
display: inline-block;
}

HTML

<ul id="myList">
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
<li>Six</li>
<li>Seven</li>
<li>Eight</li>
<li>Nine</li>    
</ul>

Fiddle here

EDIT:

Same implementation using simple javascript.

var ul = document.getElementById("myList");
var li = ul.getElementsByTagName("li");
var numItems = li.length;

var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = "ul { column-count: " + Math.round(numItems/2) + "; }";
document.body.appendChild(css);

You need to set the width of UL, because number of rows will depend on the width also even after setting the column-count. You can set it to 100% too, but then the number of rows will change based on the window size. To restrict the number of rows to 2, fixed width for UL may be required.

Therm answered 13/12, 2013 at 15:59 Comment(3)
Thanks, I would prefer a CSS solution, but if that's not possible a simple JS will do :)Tefillin
I have updated my answer to use simple javascript instead of jquery, in case you decide to go ahead with this approach :) However I haven't tested the javascript approach very well, you might have to play with it a little bit to get it to work as expected.Therm
it only worked for me, when I converted the column-count number to a string, thanks!Aaron
D
12

You could set your li at 33% width and floating against each other, once there isn't enough room in a row they will be pushed down in rows of 3 of equal width.

ul li{
  width: 33%;
  float: left;
}
Disentomb answered 13/12, 2013 at 15:49 Comment(3)
If I have 7 or more items, this would break into more than two rows, no ?Tefillin
This one would never break, it will even break the 6 itemed list to 3 lines!Saarinen
if you have 7 items you would have 3 rows, 2 full rows of 3 items and 1 row with the remaining one item, dividing the the number of items by 3, rounding up the decimals will give you your number of rowsDisentomb
T
6

I know this question is 7 years old but if anyone has similar problem today, then here's a solution using CSS Grid Layout (https://www.w3.org/TR/css-grid-1/)

ul {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
}
Tonietonight answered 13/7, 2020 at 14:5 Comment(2)
thanks for your help ♥ :)Tracheid
This answer works for three rows. If you want for example two rows, change the 3 into a 2.Exalted
S
2

Why not give it a max-width?

ul {
  max-width: somevalue; // which would last when the third item ends
}

Or, you can add class to them as

<ul>
    <li class="one">One</li>
    <li class="one">Two</li>
    <li class="one">Three</li>
    <li class="two">Four</li>
    <li class="two">Five</li>
    <li class="two">Six</li>
</ul>

Now CSS as:

.one {
  display: inline;
}

.two {
  display: inline;
}

The last thing of the padding is as

ul li {
  padding: somevalue;
} 

And for slicing:

ul {
  max-width: 200px; // to break the list
}

The good luck for you would be that you can first check the width of the list! And then slice it into two equal parts using JS, and then applying it.

If you want to get the CSS calucator, then use this:

width: calc(var1 + var2); // calc will do the math..

Here is the fiddle for this situation: http://jsfiddle.net/afzaal_ahmad_zeeshan/xN87Q/

Saarinen answered 13/12, 2013 at 15:46 Comment(5)
I have told you brother! :) You can have the function to do the calcuation, or you can use JS to get the child value! Let say, 7! Then you can increase the max-width to 230px..:)Saarinen
Ah, I see I'm going to try that, even if I would have preferred something CSS-only.Tefillin
Ok, wait ! I have a new fiddle for you, where if you add more content You still get the lists in a number of 3 :) Wait..Saarinen
jsfiddle.net/afzaal_ahmad_zeeshan/xN87Q/1 Here, try this: You will see 7 elements are aligned one under the other ..Saarinen
Yes, its a three row answer!Saarinen
N
2

Here's an example using display: flex and flex-direction: row to change the ordering from columns to rows:

#list-1 {
  border: 3px solid red;
  columns: 2;
  column-gap: 5px;
  width: 200px;
}

#list-2 {
  border: 3px solid blue;
  columns: 2;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  height: auto; /* can change this */
  width: 200px;
}

#list-2 li {
  width: 100px;
  height: auto;
}
<ul id="list-1">
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
<li>f</li>
<li>g</li>
</ul>

<ul id="list-2">
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
<li>f</li>
<li>g</li>
</ul>
Nibelungenlied answered 26/1, 2019 at 19:53 Comment(0)
E
1

you can use

li:nth-child(even) 

li:nth-child(odd)

http://jsfiddle.net/nCmZT/

Espinoza answered 13/12, 2013 at 15:56 Comment(2)
ahh... i see... to use this method the only way to guarantee only 2 rows is to give the ul a specific height, which you will have (per the question). in my fiddle, the UL does not have a height.Espinoza
Setting the height of the ul does not change the fact there are still three rows: jsfiddle.net/nCmZT/2Tefillin
G
1

Source: Creating a two column Unordered List

Fiddle : Demo provided in the link

HMTL

<ul class="two-col-special">
    <li>First Category</li>
    <li>Second Category</li>
    <li>Third Category</li>
    <li>Fourth Category</li>
    <li>Fifth Category</li>
</ul>

CSS

.two-col-special {
    border: 1px dotted blue;
    overflow: auto;
    margin: 0;
    padding: 0;
}

.two-col-special li {
    display: inline-block;
    width: 45%;
    margin: 0;
    padding: 0;
    vertical-align: top; /* In case multi-word categories form two lines */
}
.two-col-special li:before {
    content: '+';
    padding: 5px;
    margin-right: 5px; /* you can tweak the gap */
    color: orange;
    background-color: white; /* in case you want a color... */
    display: inline-block;
}
Grande answered 13/12, 2013 at 15:56 Comment(1)
I don't want a fixed number of columns, but a fixed numbers of rows.Tefillin
S
0

I think the most easies and proper way {OL tag especially} would be:

<ul>
  <div class="row">
    <div class="col-6">
      <li>One</li>
      <li>Two</li>
      <li>Three</li>
    </div>
    <div class="col-6">
      <li>Four</li>
      <li>Five</li>
      <li>Six</li>
    </div>
   </div>
</ul>
Schoolhouse answered 21/2, 2021 at 17:0 Comment(3)
Just, no: https://mcmap.net/q/326651/-can-i-use-div-as-a-direct-child-of-ulMandolin
div's inside ul's are totally legit in HTML5 and you won't be hurting anything, most of the modern browser will render with no issue so its honestly that easy. You can even wrap block elements in anchor tags, its awesomeSchoolhouse
No. The specification explicitly says you cannot. Even in HTML 5. See the answer linked above.Mandolin

© 2022 - 2024 — McMap. All rights reserved.