Search code examples
csshtml-selectcss-grid

<select multiple> ruins CSS grid


Please run the following simple grid layout example, featuring a grid cell that is a <select multiple></select>:

.grid-container {
  align-items: start;
  display: grid;
  grid-gap: 10px;
}

.grid-column-count-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-row-count-2 {
  grid-template-rows: repeat(2, min-content);
}

.col-1 {
  grid-column-start: 1;
}

.col-2 {
  grid-column-start: 2;
}

.row-1 {
  grid-row-start: 1;
}

.row-2 {
  grid-row-start: 2;
}

.rowspan-2 {
  grid-row-end: span 2;
}

.align-self-end {
  align-self: end;
}

.align-self-stretch {
  align-self: stretch;
}
<div class="grid-container grid-column-count-2 grid-row-count-2">
  <select multiple class="col-1 row-1 rowspan-2 align-self-stretch">
    <option>A</option>
    <option>B</option>
    <option>C</option>
    <option>D</option>
    <option>E</option>
  </select>
  <input type="text" class="col-2 row-1" />
  <input type="text" class="col-2 row-2 align-self-end" />
  <input type="text" class="col-2 row-1" />
</div>

The expected result is that the select element spans two rows, the height of each being defined by the <input type="text" /> elements in column 2, just like it looks if I replace the select with a simple div:

.grid-container {
  align-items: start;
  display: grid;
  grid-gap: 10px;
}

.grid-column-count-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-row-count-2 {
  grid-template-rows: repeat(2, min-content);
}

.col-1 {
  grid-column-start: 1;
}

.col-2 {
  grid-column-start: 2;
}

.row-1 {
  grid-row-start: 1;
}

.row-2 {
  grid-row-start: 2;
}

.rowspan-2 {
  grid-row-end: span 2;
}

.align-self-end {
  align-self: end;
}

.align-self-stretch {
  align-self: stretch;
}
<div class="grid-container grid-column-count-2 grid-row-count-2">
  <div class="col-1 row-1 rowspan-2 align-self-stretch" style="background-color: #f2f2f2; border: 1px solid #bbb; overflow-y: scroll;"></div>
  <input type="text" class="col-2 row-1" />
  <input type="text" class="col-2 row-2 align-self-end" />
  <input type="text" class="col-2 row-1" />
</div>

Question:

How do I style the select element in such a way that it does

  • a) have a fixed min-height of let's say 30px;
  • b) aside from that just get its height from the grid cell that it is (like the div in the second example does)

In other words:

How do I prevent the select element from affecting the row height in the grid?

Note: I cannot work with fixed-height rows.

Note 2: If a solution rather lies in a different approach as of how to define the grid-template-rows for the grid, I'm open to that as well (as long as it allows arbitrary content to define the row height). I'm unsure if my question is clear enough. Please leave a comment explaining what is unclear, and I will try my best and clarify.


Solution

  • Experimenting, I found a way to solve the issue:

    select {
      height: 24px;
      min-height: 100%;
    }
    

    seems to solve the problem. What seems very counter-intuitive about this is that min-height in this case exceeds (overwrites) height, effectively increasing it.

    select {
      height: 30px;
      min-height: 100%;
    }
    
    .grid-container {
      align-items: start;
      display: grid;
      grid-gap: 10px;
    }
    
    .grid-column-count-2 {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .grid-row-count-2 {
      grid-template-rows: repeat(2, min-content);
    }
    
    .col-1 {
      grid-column-start: 1;
    }
    
    .col-2 {
      grid-column-start: 2;
    }
    
    .row-1 {
      grid-row-start: 1;
    }
    
    .row-2 {
      grid-row-start: 2;
    }
    
    .rowspan-2 {
      grid-row-end: span 2;
    }
    
    .align-self-end {
      align-self: end;
    }
    
    .align-self-stretch {
      align-self: stretch;
    }
    <div class="grid-container grid-column-count-2 grid-row-count-2">
      <select multiple class="col-1 row-1 rowspan-2 align-self-stretch">
        <option>A</option>
        <option>B</option>
        <option>C</option>
        <option>D</option>
        <option>E</option>
      </select>
      <input type="text" class="col-2 row-1" />
      <input type="text" class="col-2 row-2 align-self-end" />
      <input type="text" class="col-2 row-1" />
    </div>