How to make the items in the last row consume remaining space in CSS Grid?

瘦欲@ 提交于 2019-12-29 06:51:27

问题


Is there a way to force all the items in the last row, of a grid, to fill the row, no matter how many they are?

I do not know the number of items that will be in the grid so I cannot target them directly. I tried to use grid-auto-flow: dense, but it is not really helping.

This is my question visualized: :

div {
  margin:20px auto;
  width: 400px;
  background: #d8d8d8;
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(3, 1fr);
}
span {
  height: 50px;
  background: blue;
}
<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>  
</div>
 

回答1:


I don't think CSS Grid is the best option for the layout you're trying to build, at least not if it's going to be dynamic and you don't really know how many items will be on the container all the time. Flexbox is actually better for one-dimensional layouts; it might be a little harder to keep everything the exact same size and using all of the available space exactly as you need it, but at the end this type of cases is what Flexbox is built for.

And of course you can make use of 100% width by using few calculations on CSS as well.

CSS Grid might be better to keep rows AND columns aligned, but this is a different case.

.container {
  display: flex;
  flex-wrap: wrap;
  box-sizing: border-box;
}

.flex-item {
  width: 30%;
  border: 1px solid #000;
  flex-grow: 1;
  min-height: 120px;
  box-sizing: border-box;
  margin: 0 5px 10px;
  justify-content: space-between;
  text-align: center;
}
<div class="container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
</div>



回答2:


This isn't possible in the current version (Level 1) of CSS Grid. However, it's not too complicated with flexbox.

You wrote in a comment:

I am using the Flexbox for the fallback. One (not the only) reason why I am looking into grids is to use "gap" and other features that come with it. For example, even though gap can be simulated by the margin, but since we do not know the number of items in the last row, getting rid of the side gaps (on the side of the container) will require extra code.

You're right: The grip-gap feature in CSS Grid is quite handy. However, you can emulate the behavior using margins – without much complexity – in flexbox, as well.

div {
  display: flex;
  flex-wrap: wrap;
  padding: 0px 0px 5px 5px;
  margin: 20px auto;
  width: 400px;
  background: #d8d8d8;

  }
span {
  flex: 1 0 30%;
  height: 50px;
  margin-top: 5px;
  margin-right: 5px;
  background: blue;
}
<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
</div>



回答3:


I have found the answer to your question. You have to use sass in order to produce the effect using math modulo function. The only factor you need is to know how many columns you have. If you know the number of columns you can apply the sass calculation and the last child will always be fluid. Finally the iteration can be bigger than 10, but for sake of the example I have limited to 10... The hard part is where modulo = 2, which means you have 2 items at the last row. There you have to change width in order to match the desired result. I used calc with 100% + half the grid gap.

@mixin setLastChildFluid{
  @for $i from 1 through 10 {    
    $span: 3;
    @if $i % 3 == 0{
      $span: 1;
    } @else if $i % 3 == 1{
      $span: 3;
    } @else if $i % 3 == 2{
      $span: 2;
    } 
    @if $span == 2 {
      span:nth-child(#{$i - 1}){
        &:nth-last-child(2){
          grid-column-end:span 1;
          position:relative;
          bottom:0;
          width:calc(150% + 5px);
          left:0;

        }
      }
      span:nth-child(#{$i}){
        &:nth-last-child(1){
          grid-column-start:2;
          position:relative;
          bottom:0;
          width:calc(150% + 5px);
          left:calc(50% + 5px);
        }
      }

    } @else {
      span:nth-child(#{$i}){
        &:last-child{
            grid-column-end:span #{$span};          
        }
      }
    }

  }
}
div {
  position:relative;
  margin:20px auto;
  width: 400px;
  background: #d8d8d8;
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(3, 1fr);

  @include setLastChildFluid;
}
span {
  height: 50px;
  background: blue;
  color:yellow;
}

and the markup (I have included two divs in order to produce both cases):

<div>
  <span>1</span>
  <span>2</span>
  <span>3</span>
  <span>4</span>
  <span>5</span>
  <span>6</span>
  <span>7</span>
  <span>8</span>
</div>
<div>
  <span>1</span>
  <span>2</span>
  <span>3</span>
  <span>4</span>
  <span>5</span>
  <span>6</span>
  <span>7</span>
</div>

The example is also here: https://jsfiddle.net/nmcobalt/dg3mutwv/13/

Change the number of divs in order to see the fluid result.




回答4:


This is totally possible with CSS grid by combining the CSS rules nth-child and nth-last-of-type. The only caveat is that the number of columns needs to be known in advance.

.grid {
    display: grid;
    grid-template-columns: auto auto auto;
    justify-items: start;
    grid-gap: 10px;
}

.grid div {
  border: 1px solid #ccc;
  width: 100%;
}

.grid > *:nth-child(3n-1) {
  justify-self: center;
  text-align: center;
}

.grid > *:nth-child(3n) {
  justify-self: end;
  text-align: right;
}

.grid > *:nth-child(3n-1):nth-last-of-type(1) {
  border-color: red;
  grid-column: span 2;
}

.grid > *:nth-child(3n-2):nth-last-of-type(1) {
  border-color: red;
  grid-column: span 3;
}
<div class="grid">
  <div>text</div>
  <div>TEXT</div>
  <div>text</div>
  <div>text</div>
  <div>TEXT</div>
  <div>text</div>
  <div>text</div>
  <div>TEXT</div>
</div>


来源:https://stackoverflow.com/questions/54370822/how-to-make-the-items-in-the-last-row-consume-remaining-space-in-css-grid

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