Reputation: 617
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 5But with 6 or more elements I want this:
1 4 2 5 3 6I 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
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
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
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
Reputation: 20925
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>
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
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