Search code examples
htmlcssgrid-layoutcss-grid

How can I collapse a row (remove a row) which doesn't have content in an explicitly declared CSS grid layout?


The question is similar to How do you collapse unused row in a CSS grid? but my rows are explicitly declared.

I have a CSS grid similar to below design:

with full content

But whenever I have no content/limited content, I'm getting some unwanted rows there. How can I remove those rows as it's adding unwanted space in my design?

I think I can't use grid-auto-rows or anything because I wanted that layout, for which I need to define the rows as in my CSS.

ref: how my layout looks when there's not enough content.

when there's not enough content

Please check the codepen:

.card {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 2fr 1fr 1fr 2fr;
  grid-gap: 5px;
}
.card * {
  /*   styles for demonstational purposes */
  background: #02750b;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 5px;
}
.card :nth-child(2) {
  grid-area: 1 / 2 / 3 / 3;
}
.card :nth-child(5) {
  grid-area: 3 / 2 / 5 / 3;
}
.card :nth-child(4) {
  grid-area: 2/ 1 / 4/ 2;
}
.card :nth-child(6) {
  grid-area: 2/ 3 / 4/ 4;
}

p  {
  padding: 5px;
  background: #b5b53f;
}
<div class="card">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>
<p>Some thing after the content</p>


Solution

  • You're defining the rows at the container level.

    .card {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      grid-template-rows: 2fr 1fr 1fr 2fr;
      grid-gap: 5px;
    }
    

    But content is handled at the grid item level.

    Therefore, when the container is asked to layout explicit tracks, it does the job without regard for the existence of content.

    In your case, when content appears or disappears, there is no change to the container rules, so there is no reason for rows to disappear.

    But I don't see any reason for explicit rows to make this layout work. Just take them out.

    Note that fr units distribute free space in the container. But you haven't set a height on the container, which means there is no free space to distribute. This may lead to unexpected behavior across major browsers (depending on how they chose to render such a scenario). Try setting a height on the container for more proper and stable behavior.

    .card {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      /* grid-template-rows: 2fr 1fr 1fr 2fr; */
      grid-gap: 5px;
    }
    .card * {
      /*   styles for demonstational purposes */
      background: #02750b;
      color: #fff;
      display: flex;
      justify-content: center;
      align-items: center;
      padding: 5px;
    }
    .card :nth-child(2) {
      grid-area: 1 / 2 / 3 / 3;
    }
    .card :nth-child(5) {
      grid-area: 3 / 2 / 5 / 3;
    }
    .card :nth-child(4) {
      grid-area: 2/ 1 / 4/ 2;
    }
    .card :nth-child(6) {
      grid-area: 2/ 3 / 4/ 4;
    }
    
    p  {
      padding: 5px;
      background: #b5b53f;
    }
    <div class="card">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
      <div>7</div>
      <div>8</div>
    </div>
    <p>Keep in mind you're using <i>fr</i> units in a container with no defined height. So expect free space to be distributed unevenly across examples.</p>
    
    
    <div class="card">
      <div>1</div>
      <div>2</div>
      <div>3</div>
     </div>
    <p>less space = smaller <i>fr</i> units = potentially shorter grid areas (browser behavior may vary)</p>