Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use css-grid to display an unknown number of items, in left-to-right reading order, over two rows?

Tags:

html

css

css-grid

I'd like to display a number of divs in left-to-right order, giving them an equal amount of space and spreading them over two rows.

e.g.

[div 1] | [div 2] | [div 3]
[div 4] | [div 5] | [div 6]

or

[div 1] | [div 2] | [div 3] | [div 4]
[div 5] | [div 6] | [div 7] | [div 8]

What's important is that I don't know how many elements there will be. If it's six, then I'll need three columns. If it's eight, then I'll need four columns. And so on.

If I give the grid container the following attributes:

  grid-auto-flow: column;
  grid-template-rows: repeat(2, 1fr);

Then my elements are given the right amount of space, but are displayed in the wrong order.

[div 1] | [div 3] | [div 5] | [div 7]
[div 2] | [div 4] | [div 6] | [div 8]

If I give the grid container the following attributes instead:

  grid-auto-flow: row;
  grid-template-rows: repeat(2, 1fr);

Then the elements appear in a single column.

[div 1]
[div 2]
...

Is there a simple way to display my elements across 2 rows, while maintaining left-to-right reading order, if I don't know how many elements there will be?

like image 459
Connor Davies Avatar asked Oct 30 '25 04:10

Connor Davies


1 Answers

A CSS only solution where you need to write a bit of CSS to cover many cases. The below code covers up to 12 elements and the CSS isn't that big. You can keep adding more to cover more cases.

.box {
  display: grid;
  grid-auto-flow:columns;
  grid-auto-columns:1fr;
  counter-reset: divs;
  margin: 5px;
  border:1px solid;
}

.box div  {
  border:1px solid red;
}

.box div:before {
  counter-increment: divs;
  content: counter(divs);
}

.box div:nth-child(1):nth-last-child(2) ~ *,
.box div:nth-child(2):nth-last-child(3) ~ *,
.box div:nth-child(3):nth-last-child(4) ~ *,
.box div:nth-child(4):nth-last-child(5) ~ *,
.box div:nth-child(5):nth-last-child(6) ~ *,
.box div:nth-child(6):nth-last-child(7) ~ *
/*
.box div:nth-child(N):nth-last-child(N+1) ~ * 
*/{
   grid-row:2;
}
<div class="box">
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
</div>


<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div> 
  <div></div> 
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
</div>

A SASS code to generate the CSS (you can try here: https://www.sassmeister.com/)

$n:12; /* make this a big as you need */

@for $i from 1 through $n {
  .box div:nth-child(#{$i}):nth-last-child(#{$i + 1}) ~ *{grid-row:2}
}

You can also cover odd number of elements:

.box {
  display: grid;
  grid-auto-flow:columns;
  grid-auto-columns:1fr;
  counter-reset: divs;
  margin: 5px;
  border:1px solid;
}

.box div  {
  border:1px solid red;
   grid-row:1;
}

.box div:before {
  counter-increment: divs;
  content: counter(divs);
}

.box div:nth-child(1):nth-last-child(2) ~ *,
.box div:nth-child(2):nth-last-child(2) ~ *,
.box div:nth-child(2):nth-last-child(3) ~ *,
.box div:nth-child(3):nth-last-child(3) ~ *,
.box div:nth-child(3):nth-last-child(4) ~ *,
.box div:nth-child(4):nth-last-child(4) ~ *,
.box div:nth-child(4):nth-last-child(5) ~ *,
.box div:nth-child(5):nth-last-child(5) ~ *,
.box div:nth-child(5):nth-last-child(6) ~ *,
.box div:nth-child(6):nth-last-child(6) ~ *,
.box div:nth-child(6):nth-last-child(7) ~ *,
.box div:nth-child(7):nth-last-child(7) ~ *{
   grid-row:2;
}
<div class="box">
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div> 
  <div></div> 
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div> 
  <div></div> 
  <div></div> 
</div>

<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
</div>

The SASS code:

$n:12;

@for $i from 1 through $n {
  .box div:nth-child(#{$i}):nth-last-child(#{$i + 1}) ~ *,
  .box div:nth-child(#{$i + 1}):nth-last-child(#{$i + 1}) ~ *{grid-row:2}
}
like image 112
Temani Afif Avatar answered Oct 31 '25 18:10

Temani Afif