Search code examples
csscss-grid

How to make a column span full width when a second column is not there? (CSS Grid)


I know there are similar questions but this is specifically asking how to do this using CSS Grid Layout.

So we have this basic grid setup:

HTML (with sidebar):

<div class="grid">

  <div class="content">
    <p>content</p>
  </div>

  <div class="sidebar">
    <p>sidebar</p>
  </div>

</div>

CSS:

.grid {
  display: grid;
  grid-template-columns: 1fr 200px;
}

To create a layout that looks something like this:

| content               | sidebar |

If the page doesn't have a sidebar though, ie. the html looks like this but with the same CSS:

HTML (no sidebar):

<div class="grid">

  <div class="content">
    <p>content</p>
  </div>

</div>

The page layout looks like this (dashes represent empty space)

| content               | ------- |

I know why it does that, the grid column is still defined in the grid-template-columns rule.

I'm just wondering how to tell the grid that if there is no content, then fill the remaining space similar to how flex-grow works for flexbox.

The desired result would look like this if no sidebar is present.

| content                         |

Solution

  • I think I know the definitive answer to this question now. The problem with the answers so far is that they don't explain how to handle a sidebar that is on the left side of the main content (mainly because I didn't ask for it in the original question).

    <div class="grid">
    
      <nav>
        <p>navigation</p>
      </nav>
    
      <main>
        <p>content</p>
      </main>
    
      <aside>
        <p>sidebar</p>
      </aside>
    
    </div>
    

    You can use this CSS:

    .grid {
      display: grid;
      grid-template-columns: fit-content(200px) 1fr fit-content(200px);
    }
    
    nav, aside {
      width: 100%;
    }
    
    /* ensures that the content will always be placed in the correct column */
    nav { grid-column: 1; }
    main { grid-column: 2; }
    aside { grid-column: 3; }
    

    This is also a good use case for grid-areas

    .grid {
      display: grid;
      grid-template-columns: fit-content(200px) 1fr fit-content(200px);
      grid-template-areas: "nav content sidebar";
    }
    
    nav, aside {
      width: 100%;
    }
    
    /* ensures that the content will always be placed in the correct column */
    nav { grid-area: nav; }
    main { grid-area: content; }
    aside { grid-area: sidebar; }
    

    An IE compatible version would look like this:

    .grid {
      display: -ms-grid;
      display: grid;
      -ms-grid-columns: auto 1fr auto;
      grid-template-columns: auto 1fr auto;
    }
    
    nav, aside {
      width: 100%; /* Ensures that if the content exists, it takes up max-width */
      max-width: 200px; /* Prevents the content exceeding 200px in width */
    }
    
    /* ensures that the content will always be placed in the correct column */
    nav {
      -ms-grid-column: 1;
      grid-column: 1;
    }
    
    main {
      -ms-grid-column: 2;
      grid-column: 2;
    }
    
    aside {
      -ms-grid-column: 3;
      grid-column: 3;
    }