Search code examples
htmlcsscss-grid

How to force CSS grid column to take as much space as possible within parent container?


I have the following layout:

.table {
  display: grid;
  grid-template-columns: fit-content(100%) auto;
}

.grid-item {
  height: 50px;
  padding: 8px;
  border: 1px solid grey;
}

.a {
  background-color: #feb5f5;
}

.b {
  background-color: #76daff;
}
<div style="display: flex; align-items: center; flex-direction: column; background-color: #ddff33">
  <div style="max-width: 1500px; background-color: #ccaa44; display:flex; align-items: first baseline; flex-direction: column;">
    <div class="table">
      <div class="grid-item a">Constant</div>
      <div class="grid-item b">Variable size content that should take as much space as possible</div>
    </div>
  </div>
</div>

It should behave according to following rules. I'm coming with WPF background but struggle to fully implement them in HTML/CSS:

  1. Page content has max width of 1500px and is horizontally centered. If viewport is smaller than 1500px, than content should shrink (in other words be responsive with upper limit).
  2. That centered content itself is a grid of two columns:
    1. Left column should take minimal horizontal space (Auto column size in WPF).
    2. Right column should take all space available (* column size in WPF):
      1. Up to hitting 1500px limit if viewport is large enough.
      2. Up to taking all viewport space left if it is smaller than 1500px.

This wouldn't be a problem without "centered 1500px" rule (1fr or auto or max-content column sizes work for me then), but as you can see in above code snipped, when inside parent container grid doesn't take all 1500px available.

StackOverflow snipped width is 800px, which means that there should be no yellow space at all here.

The problem with such behaviour is that (in my app) content of the right column can be reloaded by js code, which leads to it having zero width for a fraction of second. With current layout it means that left column "jumps" towards the center and back for a fraction of second which looks bad.

I was trying to achieve solution in two ways:

  1. Try different grid column sizes to make it take all space it can (seems to not work).
  2. Introduce additional container within 1500px container that will take all space available and center child grid to the left. I feel that this should be possible, but can't wrap my head around how exactly.
  3. Maybe I should center and limit to 1500px child grid using something else than flex container in my snippet?

If 2 would work correctly, layout with viewport >1500px would look like this: enter image description here

I also have Bootstrap 4 available but was hoping that I can use CSS grid exclusively for layout.


Solution

  • We can simply center using margin:auto

    [container] {
    /*     display: flex; */
    /*     align-items: center; */
    /*     flex-direction: column; */
        background-color: #ddff33
    }
    
    [widthconstraint] {
        max-width: 1500px;
        margin:auto;
        background-color: #ccaa44;
    /*     display: flex; */
    /*     align-items: first baseline; */
    /*     flex-direction: column; */
    }
    
    .table {
        display: grid;
        /*   grid-template-columns: fit-content(100%) auto; */
        grid-template-columns: auto 1fr;
    }
    
    .grid-item {
        height: 50px;
        padding: 8px;
        border: 1px solid grey;
    }
    
    .a {
        background-color: #feb5f5;
    }
    
    .b {
        background-color: #76daff;
    }
    <div container>
      <div widthconstraint>
        <div class="table">
          <div class="grid-item a">Constant</div>
          <div class="grid-item b">Variable size content that should take as much space as possible</div>
        </div>
      </div>
    </div>


    The issue with your code is that flex items have flex-shrink:1;flex-grow:0; by default, so they won't grow to fill the parent and they will shrink to fit their content, The fix is pretty obvious if you want to center using flexbox.

    [container] {
        display: flex;
        /*     align-items: center; */
        /*     flex-direction: column; */
        justify-content: center;
        /* Align horizontally */
        background-color: #ddff33
    }
    
    [widthconstraint] {
        flex: 1 0 0;
        max-width: 1500px;
        background-color: #ccaa44;
        display: flex;
        /* align-items: first baseline; */
        /* flex-direction: column; */
    }
    
    .table {
        flex: 1 0 0;
        display: grid;
        /*       grid-template-columns: fit-content(100%) auto; */
        grid-template-columns: auto 1fr;
    }
    
    .grid-item {
        height: 50px;
        padding: 8px;
        border: 1px solid grey;
    }
    
    .a {
        background-color: #feb5f5;
    }
    
    .b {
        background-color: #76daff;
    }
    <div container>
      <div widthconstraint>
        <div class="table">
          <div class="grid-item a">Constant</div>
          <div class="grid-item b">Variable size content that should take as much space as possible</div>
        </div>
      </div>
    </div>

    Note: The code is self explanatory, However if you have any questions please do ask. I took the liberty to clean up the code a bit