TorK
TorK

Reputation: 617

CSS/html display list in two columns if more than X amount of elements?

I have a dynamic list of elements. I do not want this list to be too long. I could use:

ul {
    columns: 2;
    -webkit-columns: 2;
    -moz-columns: 2;
}

But this always results in two columns. I would prefer to only have one column if there are only a few elements in the list. So with 5 elements or less, I want this:

1
2
3
4
5
But with 6 or more elements I want this:
1    4
2    5
3    6
I use css3, html, bootstrap 2.3.2 and jquery Do anyone have some tips for the best way to do this?

Upvotes: 6

Views: 10232

Answers (5)

Nick
Nick

Reputation: 445

Pure CSS solution: CSS Grid doesn't allow us to spread the items out evenly, column does. In that case, you can count the items in your UL. If it has more than a certain number, you can add column. Like so:

/* Splits list when more than 6 items */
ul:has( li:nth-child(7) ) {
    column-count: 2;
}
<h2>Example: 6 items</h2>
<ul>
   <li>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
   <li>Item 4</li>
   <li>Item 5</li>
   <li>Item 6</li>
</ul>
   
<h2>Example: 9 items</h2>
<ul>
   <li>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
   <li>Item 4</li>
   <li>Item 5</li>
   <li>Item 6</li>
   <li>Item 7</li>
   <li>Item 8</li>
   <li>Item 9</li>
</ul>

In this case, it splits your list when you have more than 6 items in your UL. Here a working example.

Keep in mind that the :has selector isn't fully supported yet. https://caniuse.com/css-has

Upvotes: 2

Hunter McMillen
Hunter McMillen

Reputation: 61520

If you are able to use CSS grid you can do this with grid-template-rows and grid-auto-flow directive. Grid can be used in most browsers natively and in IE11 with autoprefixer:

.list {
  display: grid;
  grid-template-rows: repeat(5, min-content);
  grid-auto-flow: column;
}
<ul class="list">
  <li class="item">1</li>
  <li class="item">2</li>
  <li class="item">3</li>
  <li class="item">4</li>
  <li class="item">5</li>
  <li class="item">6</li>
  <li class="item">7</li>
</ul>

Upvotes: 10

Marco Hengstenberg
Marco Hengstenberg

Reputation: 864

Here is a CSS only solution: http://alistapart.com/article/quantity-queries-for-css

The article explains in depth how to accomplish what you want to build.

Edit: Example! So the idea is to style lis different after the 6th list item inside a ul – otherwise put: when there are more than 5 elements we want to change layout. Possible CSS-only solution:

ul li {
  color: blue;
}

ul li:nth-child(n+6) { /* targeting all elements form the 6th on */
  color: red;
}

Of course this is assuming there are at max 12 items because otherwise the whole concept blows up or you end up with 6 items with blue color and n-elements with a red color. Anyways, this will definitely work and is an answer (maybe not the answer) to OPs question.

Edit2: In the specific case of OPs example:

ul li {
  float: left; /* list items float left */
  width: 50%;
}

ul li:nth-child(n+4) {
  float: right; /* from the fourth list item on they float right */
}

Upvotes: 0

Stewartside
Stewartside

Reputation: 20925

jQuery Method

This method uses jQuery to calculate how many elements there are and add a class based on if its 6 or more.

$(document).ready(function() {
  $('ul').each(function() {
    if ($(this).children().length > 5) {
      $(this).addClass('column');
    }
  });
});
ul.column {
  columns: 2;
  -webkit-columns: 2;
  -moz-columns: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>

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


CSS Data Attribute

If you can set a data attribute, this can be read within the CSS to calculate the outcome.

ul[data-count="even"] {
  columns: 2;
  -webkit-columns: 2;
  -moz-columns: 2;
}
<ul data-count="odd">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>

<ul data-count="even">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

Upvotes: 1

A. Wolff
A. Wolff

Reputation: 74420

You could simply filter ul element(s):

$('ul').filter(function(){
    return this.childNodes.length > 5
}).addClass('twoColumns');
ul.twoColumns {
  list-style: none;
    columns: 2;
    -webkit-columns: 2;
    -moz-columns: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
</ul>

Upvotes: 6

Related Questions