Search code examples
csscss-gridgrid-layout

Fill grid container so that last grid item area is always filled


Right now I have a grid with 1 row and 5 columns, which I'm going to be using for navigational links, but there's a chance that on some pages the grid container might not have 5 children.

The issue is that grids begin filling from the first available area.

Is there any way to fill the grid container with grid items so that instead the last area is always filled?

For example...

[a][b][c][d][ ] should be [ ][a][b][c][d]

[a][b][c][ ][ ] should be [ ][ ][a][b][c]

Notably, I do not want to reverse the direction of the elements, but rather keep the elements in the same order all the time.

Is there a simple way to do this without modifying the number of columns?


Solution

  • Since it's will only be 5 columns you can explicitly define this for each element using nth-last-child()

    .grid {
      display:grid;
      grid-template-columns:repeat(5,1fr);
      grid-gap:5px;
      margin:5px;
    }
    .grid > span {
      padding:10px;
      background:yellow;
      
    }
    
    .grid > span:nth-last-child(1) { grid-column:5; }
    .grid > span:nth-last-child(2) { grid-column:4; }
    .grid > span:nth-last-child(3) { grid-column:3; }
    .grid > span:nth-last-child(4) { grid-column:2; }
    /*.grid > span:nth-last-child(5) { grid-column:1; } this one is not needed*/
    <div class="grid">
    <span>a</span>
    <span>b</span>
    <span>c</span>
    <span>d</span>
    </div>
    
    <div class="grid">
    <span>a</span>
    <span>b</span>
    </div>
    
    <div class="grid">
    <span>a</span>
    <span>b</span>
    <span>c</span>
    <span>d</span>
    <span>e</span>
    </div>

    Or consider flexbox where it will be easier:

    .grid {
      display:flex;
      margin:5px;
      justify-content:flex-end;
    }
    .grid > span {
      padding:10px;
      background:yellow;
      width:calc(20% - 10px);
      margin:5px;
      box-sizing:border-box;
    }
    <div class="grid">
    <span>a</span>
    <span>b</span>
    <span>c</span>
    <span>d</span>
    </div>
    
    <div class="grid">
    <span>a</span>
    <span>b</span>
    </div>
    
    <div class="grid">
    <span>a</span>
    <span>b</span>
    <span>c</span>
    <span>d</span>
    <span>e</span>
    </div>


    Another idea with CSS grid where the syntax can be more intuitive and easily scalable for any number of columns:

    .grid {
      display:grid;
      grid-template-columns:repeat(var(--n,5),1fr);
      grid-gap:5px;
      margin:5px;
    }
    .grid > span {
      padding:10px;
      background:yellow;
      
    }
    
    .grid > span:nth-last-child(1) { grid-column-end:-1; }
    .grid > span:nth-last-child(2) { grid-column-end:-2; }
    .grid > span:nth-last-child(3) { grid-column-end:-3; }
    .grid > span:nth-last-child(4) { grid-column-end:-4; }
    .grid > span:nth-last-child(5) { grid-column-end:-5; }
    .grid > span:nth-last-child(6) { grid-column-end:-6; }
    
    /*.grid > span:nth-last-child(n) { grid-column-end:-n; }
      and so on ...
    */
    <div class="grid">
    <span>a</span>
    <span>b</span>
    <span>c</span>
    </div>
    <div class="grid" style="--n:4">
    <span>a</span>
    <span>b</span>
    <span>c</span>
    </div>
    
    <div class="grid" style="--n:3">
    <span>a</span>
    <span>b</span>
    </div>
    
    <div class="grid" style="--n:6">
    <span>a</span>
    <span>b</span>
    <span>c</span>
    <span>d</span>
    <span>e</span>
    </div>