htmlcsscss-grid

In CSS grid is it possible to use grid-auto-flow column but limit it to N rows before repeating?


I have these items in a grid:

01 02 03 04
05 06 07 08
09 10 11 12

My code looks like this:

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, 150px);
  gap: 10px;
  
  & > div {
    padding: 5px;
    background-color: #ccc;
  }
}
<div class="grid">
  <div>01</div>
  <div>02</div>
  <div>03</div>
  <div>04</div>
  <div>05</div>
  <div>06</div>
  <div>07</div>
  <div>08</div>
  <div>09</div>
  <div>10</div>
  <div>11</div>
  <div>12</div>
</div>

But what I need is this:

01 03 05 07
02 04 06 08
09 11
10 12

I've tried this but no cigar:

.grid {
  display: grid;
  grid-auto-flow: column; /* added this line */
  grid-template-columns: repeat(auto-fit, 150px);
  grid-template-rows: repeat(2, auto); /* added this line */
  gap: 10px;
  
  & > div {
    padding: 5px;
    background-color: #ccc;
  }
}
<div class="grid">
  <div>01</div>
  <div>02</div>
  <div>03</div>
  <div>04</div>
  <div>05</div>
  <div>06</div>
  <div>07</div>
  <div>08</div>
  <div>09</div>
  <div>10</div>
  <div>11</div>
  <div>12</div>
</div>

The solution needs to work with any number of grid items and must use auto-fit (the number of columns is unknown and depends on the available width).

I've simplified the code but in reality this lives within a @for loop within the Angular framework.

Is it possible with CSS grid? Many thanks

EDIT

If the device width only allows for 2 columns it should look like this:

01 03
02 04
05 07
06 08
09 11
10 12

Solution

  • Case for the subgrid

    Risking a wild assumption this is in fact an XY problem – since couples of items here behave as grid items, but with preserved subgrid rows for either item in the pair – then changing the flat "item" from

      <div>01 odd</div>
      <div>02 even</div>
    

    to grouping structure like

      <div>
        <div>01 odd</div>
        <div>02 even</div>
      </div>
    

    would allow quite straightforward application of the sub-grid.

    Here I took the liberty and instead of boring non-semantic divs used a definition list as the root "grid" node, then divs as its grouping nodes (it is valid since "HTML5") and definition content definition terms and descriptions for the leaf nodes:

    /*
     Grid + sub-grid
    */
    dl {
     display: grid;
     grid-template-columns: repeat(auto-fit, 150px);
     & > div {
      display: grid;
      grid-template-rows: subgrid;
      grid-row: span 2;
     }
    }
    
    /*
     Decorations
    */
    dl {
     counter-reset: item;
     overflow: hidden;
     resize: both;
     & dt,
     & dd {
      counter-increment: item;
      &::before { content: counter(item) ' '; }
      &:is(:empty)::after { opacity: .4; }
      &:is(:nth-child(odd):empty)::after { content: 'odd item' }
      &:is(:nth-child(even):empty)::after { content: 'even item' }
      margin: 1ch;
      padding: 1ch;
      background-color: color-mix(in srgb, currentcolor 10%, canvas);
     }
    }
    html { color-scheme: dark light; }
    <dl>
      <div><dt>First<dd>Comes before second</div>
      <div><dt><dd></div>
      <div><dt><dd></div>
      <div><dt><dd></div>
      <div><dt>More<br>lines<br>here<dd>Than here</div>
      <div><dt><dd></div>
      <div><dt><dd></div>
      <div><dt><dd></div>
      <div><dt>Single<br>line<dd>Is less<br>than<br>more<br>lines<br>here</div>
      <div><dt><dd></div>
      <div><dt><dd></div>
      <div><dt>Penultimate<dd>Comes before last</div>
    </dl>