Norbert
Norbert

Reputation: 2771

CSS: Arrange a list in multiple rows and columns

I have an simple ordered list inside my template file, which I can't change.

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

Is there a way to order my content like so: two columns, the last item will always be on the second column.

I tried flex, but I couldn't find a way to break the flow after the third item. Is there a way to do this via CSS or will I have to resort to hacking it with jQuery?

Upvotes: 5

Views: 4984

Answers (3)

Norbert
Norbert

Reputation: 2771

I hacked away at this for hours and haven't managed to find a suitable solution that didn't involve a fixed height on the container. The closest thing I found was using the column-count property and adding a column break before the last element, which for now only works on Chrome:

ul {
  -webkit-column-count: 2;
  column-count: 2;
}

li:last-of-type {
  -webkit-column-break-before: always;
}

JSFiddle

Upvotes: 1

Nenad Vracar
Nenad Vracar

Reputation: 122027

You can do this with Flexbox using flex-direction: column and flex-wrap: wrap, here is Fiddle

Update: This is not great solution because you have to use fixed height on parent element also if your content overflows one of li it will break layout as you can see here Fiddle but it could be useful in some cases.

body, html {
  margin: 0;
  padding: 0;
}

* {
  box-sizing: border-box;
}

ul {
  height: 100vh;
  padding: 0;
  margin: 0;
  list-style-type: none;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}

li {
  width: 50%;
}

li:nth-child(1) {
  background: #000000;
  flex: 0 0 33.33%;
}

li:nth-child(2) {
  background: #30BB75;
  flex: 0 0 33.33%;
}

li:nth-child(3) {
  background: #BB3047;
  flex: 0 0 33.33%;
}

li:nth-child(4) {
  flex: 0 0 100%;
  background: #305EBB;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

Upvotes: 4

abl
abl

Reputation: 5958

Building on Nenad Vracar's answer, you can do the same with a dynamic number of elements, without having to resort to absolute percentages, using flex-grow. Example:

ul {
  height: 200px; /* Whatever */
  list-style-type: none;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}

li {
  width: 50%;
  flex-grow: 1; /* Height will be distributed evenly */
}

li:last-of-type {
  flex: 0 0 100%; /* Last element will have 100% height,
                  thus occupying a new column */
}

JSFiddle

Upvotes: 2

Related Questions