Search code examples
htmlcsscss-grid

Make parent expand to the width of child with "display: grid"


edit: Not sure this is a duplicate? I don want the background color to extend past the width of the container, I want the container to expand to the size of its display: grid child. Updated the example to better explain my problem.

I am building a table where each row is a css grid. I have done this to leverage the minmax() of each cell, to make the whole table scrollable when its cells can't shrink anymore, while allowing the table to grow if more space is available.

This works fine besides the fact that the styling for the rows only apply to the width of the container.

Please see this example:

.container {
  width: 430px;
  background: grey;
  overflow-x: scroll;
}

.row {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) minmax(200px, 1fr) minmax(200px, 1fr) minmax(100px, 1fr);
  background: red;
  height: 3rem;
  margin: 0.5rem;
}

.cell {
  border: 1px solid black;
}
Scroll to the right inside the box:
<div class="container">
  <div class="row">
    <span class="cell">cell 1</span>
    <span class="cell">cell 2</span>
    <span class="cell">cell 3</span>
    <span class="cell">cell 4</span>
  </div>
  <div class="row">
    <span class="cell">cell 1</span>
    <span class="cell">cell 2</span>
    <span class="cell">cell 3</span>
    <span class="cell">cell 4</span>
  </div>
</div>
Elements with the <code>.row</code> class should expand to fit all the cells.

Is there any way to solve this? I'm fine with adding extra elements if need be!


Solution

  • Changing the display of the rows to inline-grid seems to help:

    .container {
      width: 430px;
      background: grey;
      overflow-x: scroll;
    }
    
    .row {
      display: inline-grid;
      grid-template-columns: minmax(200px, 1fr) minmax(200px, 1fr) minmax(200px, 1fr) minmax(100px, 1fr);
      background: red;
      height: 3rem;
    }
    
    .cell {
      border: 1px solid black;
    }
    Scroll to the right inside the box:
    <div class="container">
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
    </div>
    The red background should cover the whole row.

    Update 1

    To avoid problems with wide container/narrow children getting in one line (as with the solution above), you can use a more convoluted solution, which uses a display: flex; flex-direction: column on the parent, with additional align-items: start that forces the row items to have full width (as opposed to default stretch, which makes the row width no wider than the container).

    .container {
      width: 430px;
      background: grey;
      overflow-x: scroll;
      display: flex;
      flex-direction: column;
      align-items: start;
    }
    
    .container.container-wide{
      width: 1000px;
    }
    
    .row {
      display: grid;
      grid-template-columns: minmax(200px, 1fr) minmax(200px, 1fr) minmax(200px, 1fr) minmax(100px, 1fr);
      background: red;
      height: 3rem;
    }
    
    .cell {
      border: 1px solid black;
    }
    Scroll to the right inside the box:
    <div class="container">
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
    </div>
    Wide container:
    <div class="container container-wide">
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
    </div>
    The red background should cover the whole row.

    Update 2

    To allow for stretch of the row to the full width of the container in case it is wider than the sum of all columns, it is possible to adjust the solution from Update 1 by replacing the display: flex with display: grid, see example below:

    .container {
      width: 430px;
      background: grey;
      overflow-x: scroll;
      display: grid;
    }
    
    .container.container-wide{
      width: 1000px;
    }
    
    .row {
      display: grid;
      grid-template-columns: minmax(200px, 1fr) minmax(200px, 1fr) minmax(200px, 1fr) minmax(100px, 1fr);
      background: red;
      height: 3rem;
    }
    
    .cell {
      border: 1px solid black;
    }
    Scroll to the right inside the box:
    <div class="container">
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
    </div>
    Wide container:
    <div class="container container-wide">
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
      <div class="row">
        <span class="cell">cell 1</span>
        <span class="cell">cell 2</span>
        <span class="cell">cell 3</span>
        <span class="cell">cell 4</span>
      </div>
    </div>
    The red background should cover the whole row.