Search code examples
csscss-grid

How to stretch only one of several css grid areas


You'll have to play a little with screen dimensions to see what I mean.

Say I've got a card, which is inside a grid row, which is taller than the card. This card is 100% height, and the inner css grid ( element) should also be 100% height. But if I put height: 100% in the grid element (.post-card a), the height of all the rows are affected. They are grid areas. I would like that only the last one (.bottom-2) will fill the remaining vertical space of the outer grid cell, while the "main" inner grid area still respect the aspect-ratio I setted for .image, and .title section be tall as its content. In other words, all as currently shown in the snippet, except the last row filling the empty space. How can I do this?

body > div + div{
  margin-top: 2em;
}

.grid{
  display: grid;
  height: 100vh;
}

.post-card{
  border: 1px solid #000;
  height: 100%;
}

.post-card a{
  display: grid;
  grid-template-areas: 
    "main"
    "main"
    "bottom-1"
    "bottom-2";
}

.date{
  grid-row: 1/2;
  grid-column: 1/2;
  width: fit-content;
  background-color: #000;
  z-index:10;
}

.image{
  grid-area: main;
  aspect-ratio: 16/3;
  background-color: #0e0;
}

.title{
  grid-area: bottom-1;
  background-color: #0ee;
}

.bottom-2{
  grid-area: bottom-2;
  
  display: flex;
  background-color: #ee0;  
}

.share{
  width: 30px;
  background-color: #e0e;
}
<div class="grid">
<div class="post-card image-title-cta">
  <a href="#">
    <div class="date">date</div>
    <div class="image">image</div>
    <div class="title">title</div>
    <div class="bottom-2">
      <div class="cta">cta</div>
      <div class="share">share</div>
    </div>
  </a>
</div>
</div>


Solution

  • You are correct that you need to set .post-card a {height: 100%}, but to get the rows to behave as you want to, you need to add a grid-template-rows style as well.

    If I understand you correctly, you want the first three grid rows to be sized to fit their contents, so you need to set them to auto. Then you want the fourth grid row to stretch to fill the remaining space in the grid, so it needs to be set to 1fr. Fractional units are all about how to divide the remaining space in the grid after all other constraints have been satisfied.

    .post-card a {
      height: 100%;
      grid-template-rows: auto auto auto 1fr;
    }
    

    A snippet to demonstrate:

    body {
      margin: 0;
    }
    
    body > div + div{
      margin-top: 2em;
    }
    
    .grid {
      display: grid;
      height: 100vh;
    }
    
    .post-card {
      height: 100%;
    }
    
    .post-card a {
      height: 100%;
      display: grid;
      grid-template-rows: auto auto auto 1fr;
      grid-template-areas: 
        "main"
        "main"
        "bottom-1"
        "bottom-2";
    }
    
    .date{
      grid-row: 1/2;
      grid-column: 1/2;
      width: fit-content;
      background-color: #000;
      z-index:10;
    }
    
    .image { 
      grid-area: main;
      aspect-ratio: 16/3;
      background-color: #0e0;
      background-image: url(http://picsum.photos/id/304/1600/600);
      background-size: cover;
      background-position: 50% 70%;
    }
    
    .title {
      grid-area: bottom-1;
      background-color: #0ee;
    }
    
    .bottom-2 {
      grid-area: bottom-2;
      display: flex;
      justify-content: space-between;
      background-color: #ee0;
    }
    
    .share {
      background-color: #e0e;
    }
    <div class="grid">
    <div class="post-card image-title-cta">
      <a href="#">
        <div class="date">date</div>
        <div class="image">image</div>
        <div class="title">title</div>
        <div class="bottom-2">
          <div class="cta">cta</div>
          <div class="share">share</div>
        </div>
      </a>
    </div>
    </div>

    After running the snippet, make sure to use the full page link to see the effect properly.