Search code examples
htmlcsscss-gridcss-tables

Last row in CSS Grid where cells have a footer and are stretched to same height drawing strangely


I have a code pen at https://codepen.io/james-hudson3010/pen/wveJqXd

What I am looking to achieve is the following:

  1. I have an arbitrary number of cells. This example only uses 10, but it could be more or less than 10

  2. Each cell has a footer which needs to be aligned to the bottom of cell so that they are aligned across cells in the same row

  3. The height of a cell can vary, but the height needs to be stretched so every cell in the same row has the same height to support #2

This almost works perfectly using Safari ( Version 14.1.2 (15611.3.10.1.5, 15611) ), but the last cell in the last row is wider than it should be.

Safari

The behavior is worse in Chrome ( Version 93.0.4577.63 (Official Build) (x86_64) ). The rows are drawn higher than they should be. The last cell in the last row is to wide.

Chrome

Is this due to a lack of complete browser support?

If this is due to not specifying my css correctly, what do I need to do?

.example1 {
  display: grid;
  grid-template-columns: repeat(auto-fill, 300px);
  align-items: stretch;
}

div {
  border: solid 1px;
  padding: 1rem;
}

.contentdiv {
  background-color: red;
  display: table;
  height: 100%;
  width: 100%;
}

.foot {
  display: table-row;
  vertical-align: bottom;
  height: 1px;
}
<div class="example1">
  <div class="contentdiv">1<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
    <div class="foot">bottom</div>
  </div>
  <div class="contentdiv">2
    <div class="foot">bottom</div>
  </div>
  <div class="contentdiv">3
    <div class="foot">bottom</div>
  </div>
  <div class="contentdiv">4
    <div class="foot">bottom</div>
  </div>
  <div class="contentdiv">5a<br/>a<br/>a<br/>a<br/>
    <div class="foot">bottom</div>
  </div>
  <div class="contentdiv">6
    <div class="foot">bottom</div>
  </div>
  <div class="contentdiv">7a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
    <div class="foot">bottom</div>
  </div>
  <div class="contentdiv">8
    <div class="foot">bottom</div>
  </div>
  <div class="contentdiv">9
    <div class="foot">bottom</div>
  </div>
  <div class="contentdiv">10a<br/>a<br/>a<br/>
    <div class="foot">bottom</div>
  </div>
</div>


Solution

  • This has to do with the setting the display to table for the contentdiv - and setting it's width and height to 100%.

    Basically what is happening - if you view your elements in the web inspector - you'll see that all of your elements are wider than 300px because of the padding 1rem, so they are actually overlapping already, you just can't visually see it until the last row.

    You can avoid this setting, * { box-sizing: border-box } and the display to flex instead, and using the justify-content property to keep the foot aligned on all rows:

    * {
      box-sizing: border-box;
    }
    
    .example1 {
      display: grid;
      grid-template-columns: repeat(auto-fill, 300px);
      align-items: stretch;
    }
    
    div {
      border: solid 1px;
      padding: 1rem;
    }
    
    .contentdiv {
      background-color: red;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      /* Avoid the borders stacking */
      margin: -1px;
    }
    <div class="example1">
      <div class="contentdiv">1<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
        <div class="foot">bottom</div>
      </div>
      <div class="contentdiv">2
        <div class="foot">bottom</div>
      </div>
      <div class="contentdiv">3
        <div class="foot">bottom</div>
      </div>
      <div class="contentdiv">4
        <div class="foot">bottom</div>
      </div>
      <div class="contentdiv">5a<br/>a<br/>a<br/>a<br/>
        <div class="foot">bottom</div>
      </div>
      <div class="contentdiv">6
        <div class="foot">bottom</div>
      </div>
      <div class="contentdiv">7a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
        <div class="foot">bottom</div>
      </div>
      <div class="contentdiv">8
        <div class="foot">bottom</div>
      </div>
      <div class="contentdiv">9
        <div class="foot">bottom</div>
      </div>
      <div class="contentdiv">10a<br/>a<br/>a<br/>
        <div class="foot">bottom</div>
      </div>
    </div>