Search code examples
htmlcsscss-grid

How to align columns in nested HTML using CSS grid


I need to use a grid, but my columns are not direct children of the grid. The grid has two columns:

  1. Column 1 contains the label.
  2. Column 2 contains the input box.

The label column should be as large (but not larger) than the largest column. The input column should use all remaining space. I attempted the following CSS/HTML combo.

* {
  border: 1px solid black;
  background: #2222;
}

.container {
  display: grid;
  width: 550px;
  grid-gap: 10px;
  grid-template-rows: [a] auto [b] auto [c] auto;
  grid-template-columns: [label] auto [input] 1fr;
  align-items: stretch;
}

label { grid-column-start: label; }
input { grid-column-start: input; }

.a { grid-row-start: a; }
.b { grid-row-start: b; }
.c { grid-row-start: c; }
<div class="container">
  <div class="a">
    <label>A</label>
    <input>
  </div>
  <div class="b">
    <label>Label B</label>
    <input>
  </div>
  <div class="c">
    <label>Longest C label</label>
    <input>
  </div>
</div>

I understand that the grid-column-start isn't used, because the elements are not direct children of the grid. But how can I accomplish this functionality without hardcoding the label width or use Javascript?

Using multiple grids (one per row) would be fine, but I would need to synchronized the widths of the first column. I have read about subgrids, but it's not implemented by any major browser yet. Do I have other alternatives to solve this issue?


Solution

  • This seems to be more suitable for table layout than CSS grid:

    * {
     box-sizing:border-box;
    }
    .container {
      display: table;
      width: 550px;
      border:1px solid;
    }
    
    .container>div {
      display: table-row;
    }
    
    label,
    input {
      display: table-cell;
      border:1px solid green;
    }
    label {
      width:5%; /*a small value*/
      white-space:nowrap;
    }
    input {
     width:100%;
    }
    <div class="container">
      <div class="a">
        <label>A</label>
        <input>
      </div>
      <div class="b">
        <label>Label B</label>
        <input>
      </div>
      <div class="c">
        <label>Longest C label</label>
        <input>
      </div>
    </div>