Search code examples
cssflexboxcss-grid

Grid is not sizing correctly in row direction


Background

I am trying to build a page with main section containing a dynamic grid in between a header and footer. As users use the page, book shaped .grid-item divs are appended to the .grid. Initially, when the .grid is empty, I want the <main> to expand to fill the page space so the footer isn't floating half way up the page. As the grid grows beyond the confines of this space, I want the page to grow vertically so that it scrolls.

Book shape

By book shaped, I mean that the column should be 2/3 the size of the height for each grid item.

Problem

The problem is that only the columns of the grid are behaving as intended with the items equally sized. In the row direction, only the first row is working as intended and the following rows are only the height of the content. As a result, they are no longer book shaped.

Solutions tried

I added flex: 1 to the <main> so that it can grow as needed. I also used grid-template-rows: repeat(auto-fill, minmax(300px, 1fr)); so that it would auto-fill the grid with equally sized rows.

Following this, I tried to auto-fill the grid with static sized columns and rows:

grid-template-columns: repeat(auto-fill, 200px);
grid-template-rows: repeat(auto-fill, 300px);

After this, I did some reading on the repeat() function and auto-fill to see where my misunderstanding is. I also searched stack-overflow for similar issues and attempted some mentioned solutions like changing my flex-grow and flex-basis for the <main> but I could not resolve the issue.

Closest Solution

I found that if I change the rows explicitly instead of using auto-fill, then the rows work as intended.

grid-template-rows: repeat(12, minmax(250px, 1fr));

This would however require for me to use javascript to change the styling of the .grid as I append children. This solution doesn't work because if the page width changes so that there are fewer columns, the rows would increase automatically, so it would add a lot of extra work to calculate the required rows using javascript before changing the styling. For this reason, I am ideally looking for a CSS only solution.

body {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-height: 100vh;
    margin: 0;
    padding: 0;
}

header, footer {
  height: 40px;
}

main {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: center;
    background-color: grey;
    width: 100%;
}

.grid {
    display: grid;
    width: 60vw;
    margin: 5px var(--margin-size) 5px var(--margin-size);
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    grid-template-rows: repeat(auto-fill, minmax(300px, 1fr));
    gap: 10px;
}

.grid-item {
  background-color: red;
}
<body>
  <header>
    Header
  </header>
  <main>
    <div class="grid">
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
      <div class="grid-item">
        Grid Item
      </div>
    </div>
  </main>
  <footer>
    Footer
  </footer>
<body>

My question is how can I make the grid grow beyond the confines of the screen while retaining the book shape of the grid children?


Solution

  • I was able to get it working as intended with:

    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    grid-auto-rows: minmax(300px, 1fr);
    

    Working snippet below:

    body {
        display: flex;
        flex-direction: column;
        align-items: center;
        min-height: 100vh;
        margin: 0;
        padding: 0;
    }
    
    header, footer {
      height: 40px;
    }
    
    main {
        flex: 1;
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: center;
        background-color: grey;
        width: 100%;
    }
    
    .grid {
        display: grid;
        width: 60vw;
        margin: 5px var(--margin-size) 5px var(--margin-size);
        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
        grid-auto-rows: minmax(300px, 1fr);
        gap: 10px;
    }
    
    .grid-item {
      background-color: red;
    }
    <body>
      <header>
        Header
      </header>
      <main>
        <div class="grid">
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
          <div class="grid-item">
            Grid Item
          </div>
        </div>
      </main>
      <footer>
        Footer
      </footer>
    <body>