4

I have an unknown amount of items that need to be displayed in a grid. I'd like the number of columns to auto-fill as needed, with no limit on the number of rows. I can get this working just fine:

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  list-style: none;
}
<ul class="grid">
  <li>a</li>
  <li>b</li>
  <li>c</li>
  <li>d</li>
  <li>e</li>
  <li>f</li>
  <li>g</li>
  <li>h</li>
</ul>

However, I'd also like the items to be sorted alphabetically by column:

a  d  g
b  e  h
c  f

I know I can use grid-auto-flow: column to place each item by column instead of by row, but if I do that, I just get one long row.

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-auto-flow: column;
  list-style: none;
}
<ul class="grid">
  <li>a</li>
  <li>b</li>
  <li>c</li>
  <li>d</li>
  <li>e</li>
  <li>f</li>
  <li>g</li>
  <li>h</li>
</ul>

How can I keep the behavior of the first snippet but with sorting from top to bottom instead of from left to right?

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Christian Jensen
  • 900
  • 1
  • 10
  • 25
  • you need to define a row template in the second case or it's like having only one row – Temani Afif Apr 17 '19 at 22:45
  • But I'd like to have unlimited rows. So I could do something like `grid-template-rows: repeat(10, 50px)`, but then I only get 10 rows. I want the rows to handle any amount of data. – Christian Jensen Apr 17 '19 at 22:48
  • You have no limit for the rows, then how many rows do you expect to be ? like always two even columns ? – Rainbow Apr 17 '19 at 22:48
  • I know, I am simply explaining how the second case is working and how to avoid what you had. with no row defined, the browser will consider only one (also don't forget window resizing and wrapper changing, etc) – Temani Afif Apr 17 '19 at 22:49
  • @ZohirSalak I would expect there to be as many rows as there is data to fill out. So if the viewport is 600px wide, I would have 3 columns or less (since each has a minimum width of 200px), and however many rows would be produced by how ever many items there are. – Christian Jensen Apr 17 '19 at 22:50

2 Answers2

3

I think the only way to do this is to consider JS and dynamically adjust the number of rows.

Here is a simplified example where you will need a more complete code if you will have gap, padding, etc

var minv = 200; 
var grid = document.querySelector('.grid');
var nb   = document.querySelectorAll('.grid li').length;

var nb_row = Math.ceil(nb/Math.floor(grid.offsetWidth/200));
/* grid.offsetWidth/200 = X will give the number of columns
   nb/X will give the number of rows
   
   We use floor with the first as we won't have overflow but a wrap (so 3.2 should be 3)
   We use ceil with the second one as we may have the last row with fewer elements (so 3.2 should be 4)

*/

grid.style.gridTemplateRows="repeat("+nb_row+",auto)";

window.addEventListener('resize', function(event){
   nb_row = Math.ceil(nb/Math.floor(grid.offsetWidth/200));
   grid.style.gridTemplateRows="repeat("+nb_row+",auto)";
});
.grid {
  display: grid;
  grid-auto-columns: minmax(200px, 1fr);
  grid-auto-flow: column;
  list-style: none;
  padding:0;
}
<ul class="grid">
  <li>a</li>
  <li>b</li>
  <li>c</li>
  <li>d</li>
  <li>e</li>
  <li>f</li>
  <li>g</li>
  <li>h</li>
</ul>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
1

You can use grid-template-rows to limit the amount of rows, so the grid can calculate the items for each column.

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-template-rows: repeat(3, 100px);
  grid-auto-flow: column;
  list-style: none;
}
<ul class="grid">
  <li>a</li>
  <li>b</li>
  <li>c</li>
  <li>d</li>
  <li>e</li>
  <li>f</li>
  <li>g</li>
  <li>h</li>
</ul>
IvanS95
  • 5,364
  • 4
  • 24
  • 62
  • I need to have no limit on the number of rows (see first part of question) – Christian Jensen Apr 17 '19 at 22:47
  • Okay, but then there's an issue, you want both columns to auto fill and rows to be dynamic, but I don't think you can do that since you need some way to tell the structure how to distribute the items, it *needs* to know how many items it can put on each row or in each column, and then it can handle the other direction on its own – IvanS95 Apr 17 '19 at 22:49
  • I thought by telling it that each column has to be at least 200px it would know that it can only fit, say, 3 columns in a 600px wide viewport, which I would think would enable it to know how to render the rows. But I am guessing there's just no way to do this. – Christian Jensen Apr 17 '19 at 22:52