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

邮差的信 提交于 2021-02-15 07:36:52

问题


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?


回答1:


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}
}



回答2:


You will need javascript to calculate a min-width value for the grid column , then auto-fit,mimax() can do.

possible example

let yop =document.querySelectorAll('#test  div')
document.body.style.setProperty('--minWidth', Math.ceil(200 / yop.length) -1 +'%' );
#test {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--minWidth), 1fr));
  counter-reset: divs;
  /* width:800px; or not */
}

div div  {
  border: solid;
  box-sizing:border-box;
}

div div:before {
  counter-increment: divs;
  content: counter(divs);
}
<div id="test">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div> 
  <div></div> 
</div>

Its a basic approach , a percentage calculated from 200 willdraw 2 rows, 300 will draw 3 rows and so on.

But it can be a flex layout or floatting element, grid is not the magic here. CSS is unable to read the dom and adapt a value on the fly like you would wish.



来源:https://stackoverflow.com/questions/65240397/can-i-use-css-grid-to-display-an-unknown-number-of-items-in-left-to-right-readi

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!