Search code examples
csscss-grid

Why does input's size increase in CSS Grid layouts?


I have a few questions in the context of CSS grid with regard to <input> elements.

  1. Why does the label's and input's size match the grid's row height and fills it in?
  2. Why are the label and input elements displayed as block in CSS grid but as inline elements in a simple div?
  3. Why is my attempt at overriding their display to be inline ignored by the browser?

Finally, there's an implicit "how can I fix this" question here.

Here is an example:

.wrapper {
  background-color: purple;
  display: grid;
  grid-template-columns: 1fr 4rem 4rem 1fr;
}

.wrapper > label {
  display: inline;
   grid-column: 2;
  background-color:green;
}
.wrapper > input[type=checkbox] {
   grid-column: 3;
  border: 1px solid red;
  background-color: gray;
}

.wrapper > input[type=text] {
   grid-column: 4;
 outline: 2px solid yellow;
}

.simple {
  width: 50px;
  height: 100px;
  background-color: blue;
}

.simple > label {
    height: 50px;
}


.wrapper2 {
  background-color: gray;
  display: grid;
   grid-template-rows: 100px;
    grid-auto-rows: 100px;
  grid-template-columns: 1fr 8rem 8rem 1fr;
}

.wrapper2 > label {
   grid-column: 2;
  display: inline;
  background-color:green;
}
.wrapper2 > input[type=checkbox] {
   grid-column: 3;
  background-color:yellow;
  border: 1px solid gray;
}

.wrapper2 > input[type=text] {
   grid-column: 4;
  outline: 2px solid yellow;
  border: 1px solid gray;
}
<div class="wrapper">
  <label for="cb">Long Label</label>
  <input id="cb" type="checkbox">
    <input id="t3" type="text">
</div>

<div class="simple">
  <label for="cb2">Long Label</label>
  <input id="cb2" type="checkbox">
  <input id="t2" type="text">
</div>
  
 <div class="wrapper2">
  <label for="cb3">Long Label</label>
  <input id="cb3" type="checkbox"> 
   <input id="t3" type="text"> 
</div>


Solution

  • 1. Why does the label's and input's size match the grid's row height and fills it in?

    Because height is auto, in CSS Grid auto is stretched. because of the default value stretch of the alignment properties align-items and justify-content, We can override this:

    1. align-items:flex-start in the block axis (vertically)
    2. justify-content:flex-start in the inline axis (horizontally)

    [grid] {
      background: orange;
      display: inline-grid;
      grid-template-columns: 50px;
      grid-template-rows: 50px;
    }
    
    [grid]>div {
      background: red;
      height: auto;
    }
    
    [fix] {
      align-items: flex-start;
      justify-items: flex-start;
    }
    
    [grid]>[notAuto] {
      height: 30px;
      width: 30px;
    }
    <h4>align-items: stretch; justify-items: stretch; (default)</h4>
    <div grid>
      <div>Text</div>
    </div>
    
    <h4>align-items: flex-start; justify-items: flex-start;</h4>
    <div grid fix>
      <div>Text</div>
    </div>
    
    
    <h4>When width/height are specified (not auto)</h4>
    <div grid>
      <div notAuto>Text</div>
    </div>

    Note: we can override that behavior on specific elements using their -self counterpart justify-self align-self on the Grid items instead of the container


    2. Why are the label and input elements displayed as blocks in css grid but as inline elements in a simple div?

    3. Why is overriding their display to inline is ignored by the browser?

    The spec says:

    The display value of a grid item is blockified: if the specified display of an in-flow child of an element generating a grid container is an inline-level value, it computes to its block-level equivalent.