Search code examples
htmlcsscss-grid

CSS grid, problem with dynamically spaning rows when there is elements with bigger height


I have a css grid applied to a form layout, with dynamic number of elements per column, with code in React, for start i have first scenario (picture bellow), before tweaks i added to improve it a bit but still not working as expected:

enter image description here

As you can see here, one of the problems is causing text area which has height bigger than it is for text input which cause that whole row gets expanded which is also unexpected, corresponding html/css code for this is:

<fieldset
  class="form-section"
  style="display:grid; grid-gap: 1rem; grid-template-columns: repeat(3, min-content 1fr); 
  align-items: start"
>
  <div style="grid-area: 1 / 1 / auto / span 1; place-self: center left">
    <label
      for="Email-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">Email</span><span class="">&nbsp;*</span></label
    >
  </div>
  <div style="grid-area: 1 / 2 / auto / span 1">
    <input
      type="text"
      id="Email-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="255"
      data-testid="input-text"
      value=""
      style="width: 300px"
    />
  </div>
  <div
    style="
      grid-area: 1 / 3 / auto / span 1;
      justify-self: left;
      padding-top: 1rem;
    "
  >
    <label
      for="Last_Name-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">Last Name</span></label
    >
  </div>
  <div style="grid-area: 1 / 4 / auto / span 1">
    <textarea
      id="Last_Name-e4400000754e818c2bb0408a8dce"
      rows="5"
      cols="50"
      class="p-inputtextarea p-inputtext p-component"
    ></textarea>
  </div>
  <div style="grid-area: 1 / 5 / auto / span 1; place-self: center left">
    <label
      for="fieldInt-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">fieldInt</span><span class="">&nbsp;*</span></label
    >
  </div>
  <div style="grid-area: 1 / 6 / auto / span 1">
    <input
      type="text"
      id="fieldInt-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="10"
      data-testid="input-text"
      value=""
    />
  </div>
  <div style="grid-area: 2 / 1 / auto / span 1; place-self: center left">
    <label
      for="Phone-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">Phone</span><span class="">&nbsp;*</span></label
    >
  </div>
  <div style="grid-area: 2 / 2 / auto / span 1">
    <input
      type="text"
      id="Phone-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="15"
      data-testid="input-text"
      value=""
    />
  </div>
  <div style="grid-area: 2 / 3 / auto / span 1; place-self: center left">
    <label
      for="List_Numbers-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">List Numbers</span></label
    >
  </div>
  <div style="grid-area: 2 / 4 / auto / span 1">
    <div
      id="List_Numbers-e4400000754e818c2bb0408a8dce-component"
      class="p-multiselect p-component p-inputwrapper"
      style="width: 236px"
    >
      <div class="p-hidden-accessible">
        <input
          id="List_Numbers-e4400000754e818c2bb0408a8dce"
          readonly=""
          type="text"
          role="listbox"
          aria-expanded="false"
          tabindex="0"
        />
      </div>
      <div class="p-multiselect-label-container">
        <div class="p-multiselect-label p-multiselect-label-empty">empty</div>
      </div>
      <div class="p-multiselect-trigger">
        <svg
          width="14"
          height="14"
          viewBox="0 0 14 14"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          class="p-icon p-multiselect-trigger-icon p-c"
          aria-hidden="true"
        >
          <path
            d="M7.01744 10.398C6.91269 10.3985 6.8089 10.378 6.71215 10.3379C6.61541 10.2977 6.52766 10.2386 6.45405 10.1641L1.13907 4.84913C1.03306 4.69404 0.985221 4.5065 1.00399 4.31958C1.02276 4.13266 1.10693 3.95838 1.24166 3.82747C1.37639 3.69655 1.55301 3.61742 1.74039 3.60402C1.92777 3.59062 2.11386 3.64382 2.26584 3.75424L7.01744 8.47394L11.769 3.75424C11.9189 3.65709 12.097 3.61306 12.2748 3.62921C12.4527 3.64535 12.6199 3.72073 12.7498 3.84328C12.8797 3.96582 12.9647 4.12842 12.9912 4.30502C13.0177 4.48162 12.9841 4.662 12.8958 4.81724L7.58083 10.1322C7.50996 10.2125 7.42344 10.2775 7.32656 10.3232C7.22968 10.3689 7.12449 10.3944 7.01744 10.398Z"
            fill="currentColor"
          ></path>
        </svg>
      </div>
    </div>
  </div>
  <div style="grid-area: 2 / 5 / auto / span 1; place-self: center left">
    <label
      for="dateCreated-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">dateCreated</span></label
    >
  </div>
  <div style="grid-area: 2 / 6 / auto / span 1">
    <span
      class="p-calendar p-component p-inputwrapper p-calendar-w-btn p-calendar-w-btn-right"
      ><input
        id="dateCreated-e4400000754e818c2bb0408a8dce"
        type="text"
        class="p-inputtext p-component"
        autocomplete="off"
        inputmode="none"
      /><button
        type="button"
        tabindex="-1"
        class="p-button p-component p-datepicker-trigger p-button-icon-only"
      >
        <span class="pi pi-calendar"></span
        ><span class="p-button-label p-c">&nbsp;</span>
      </button></span
    >
  </div>
  <div style="grid-area: 3 / 1 / auto / span 1; place-self: center left">
    <label
      for="text64-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">text64</span></label
    >
  </div>
  <div style="grid-area: 3 / 2 / auto / span 1">
    <input
      type="password"
      id="text64-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="64000"
      data-testid="input-text"
      value=""
    />
  </div>
  <div style="grid-area: 3 / 3 / auto / span 1; place-self: center left">
    <label
      for="First_Name-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">First Name</span></label
    >
  </div>
  <div style="grid-area: 3 / 4 / auto / span 1">
    <input
      type="text"
      id="First_Name-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="255"
      data-testid="input-text"
      value=""
    />
  </div>
</fieldset>

what i did here to improve this is that i set grid-row-end for multiline form elements, in this case it is textarea element to span 2, and to all elements which are bellow this element to grid-row: auto and this looks like this:

<fieldset
  class="form-section"
  style="grid-template-columns: repeat(3, min-content 1fr); align-items: start"
>
  <div style="grid-area: 1 / 1 / auto / span 1; place-self: center left">
    <label
      for="Email-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">Email</span><span class="">&nbsp;*</span></label
    >
  </div>
  <div style="grid-area: 1 / 2 / auto / span 1">
    <input
      type="text"
      id="Email-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="255"
      data-testid="input-text"
      value=""
      style="width: 300px"
    />
  </div>
  <div
    style="
      grid-area: 1 / 3 / span 2 / span 1;
      justify-self: left;
      padding-top: 1rem;
    "
  >
    <label
      for="Last_Name-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">Last Name</span></label
    >
  </div>
  <div style="grid-area: 1 / 4 / span 2 / span 1">
    <textarea
      id="Last_Name-e4400000754e818c2bb0408a8dce"
      rows="5"
      cols="50"
      class="p-inputtextarea p-inputtext p-component"
    ></textarea>
  </div>
  <div style="grid-area: 1 / 5 / auto / span 1; place-self: center left">
    <label
      for="fieldInt-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">fieldInt</span><span class="">&nbsp;*</span></label
    >
  </div>
  <div style="grid-area: 1 / 6 / auto / span 1">
    <input
      type="text"
      id="fieldInt-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="10"
      data-testid="input-text"
      value=""
    />
  </div>
  <div style="grid-area: 2 / 1 / auto / span 1; place-self: center left">
    <label
      for="Phone-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">Phone</span><span class="">&nbsp;*</span></label
    >
  </div>
  <div style="grid-area: 2 / 2 / auto / span 1">
    <input
      type="text"
      id="Phone-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="15"
      data-testid="input-text"
      value=""
    />
  </div>
  <div style="grid-area: auto / 3 / auto / span 1; place-self: center left">
    <label
      for="List_Numbers-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">List Numbers</span></label
    >
  </div>
  <div style="grid-area: auto / 4 / auto / span 1">
    <div
      id="List_Numbers-e4400000754e818c2bb0408a8dce-component"
      class="p-multiselect p-component p-inputwrapper"
      style="width: 236px"
    >
      <div class="p-hidden-accessible">
        <input
          id="List_Numbers-e4400000754e818c2bb0408a8dce"
          readonly=""
          type="text"
          role="listbox"
          aria-expanded="false"
          tabindex="0"
        />
      </div>
      <div class="p-multiselect-label-container">
        <div class="p-multiselect-label p-multiselect-label-empty">empty</div>
      </div>
      <div class="p-multiselect-trigger">
        <svg
          width="14"
          height="14"
          viewBox="0 0 14 14"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          class="p-icon p-multiselect-trigger-icon p-c"
          aria-hidden="true"
        >
          <path
            d="M7.01744 10.398C6.91269 10.3985 6.8089 10.378 6.71215 10.3379C6.61541 10.2977 6.52766 10.2386 6.45405 10.1641L1.13907 4.84913C1.03306 4.69404 0.985221 4.5065 1.00399 4.31958C1.02276 4.13266 1.10693 3.95838 1.24166 3.82747C1.37639 3.69655 1.55301 3.61742 1.74039 3.60402C1.92777 3.59062 2.11386 3.64382 2.26584 3.75424L7.01744 8.47394L11.769 3.75424C11.9189 3.65709 12.097 3.61306 12.2748 3.62921C12.4527 3.64535 12.6199 3.72073 12.7498 3.84328C12.8797 3.96582 12.9647 4.12842 12.9912 4.30502C13.0177 4.48162 12.9841 4.662 12.8958 4.81724L7.58083 10.1322C7.50996 10.2125 7.42344 10.2775 7.32656 10.3232C7.22968 10.3689 7.12449 10.3944 7.01744 10.398Z"
            fill="currentColor"
          ></path>
        </svg>
      </div>
    </div>
  </div>
  <div style="grid-area: 2 / 5 / auto / span 1; place-self: center left">
    <label
      for="dateCreated-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">dateCreated</span></label
    >
  </div>
  <div style="grid-area: 2 / 6 / auto / span 1">
    <span
      class="p-calendar p-component p-inputwrapper p-calendar-w-btn p-calendar-w-btn-right"
      ><input
        id="dateCreated-e4400000754e818c2bb0408a8dce"
        type="text"
        class="p-inputtext p-component"
        autocomplete="off"
        inputmode="none"
      /><button
        type="button"
        tabindex="-1"
        class="p-button p-component p-datepicker-trigger p-button-icon-only"
      >
        <span class="pi pi-calendar"></span
        ><span class="p-button-label p-c">&nbsp;</span>
      </button></span
    >
  </div>
  <div style="grid-area: 3 / 1 / auto / span 1; place-self: center left">
    <label
      for="text64-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">text64</span></label
    >
  </div>
  <div style="grid-area: 3 / 2 / auto / span 1">
    <input
      type="password"
      id="text64-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="64000"
      data-testid="input-text"
      value=""
    />
  </div>
  <div style="grid-area: 3 / 3 / auto / span 1; place-self: center left">
    <label
      for="First_Name-e4400000754e818c2bb0408a8dce"
      class="CaspioFormField-module_form-field-label-H5HRq"
      ><span class="">First Name</span></label
    >
  </div>
  <div style="grid-area: 3 / 4 / auto / span 1">
    <input
      type="text"
      id="First_Name-e4400000754e818c2bb0408a8dce"
      class="p-inputtext p-component"
      maxlength="255"
      data-testid="input-text"
      value=""
    />
  </div>
</fieldset>

and this looks better:

enter image description here

but as now i added that textarea spans only two rows, if i tend to get something like this:

enter image description here

the space between these two inputs is bigger as they tend to fill the corresponding height of the text area, and if for example i add bigger height of text area i get bigger gap:

enter image description here

and if i try to dynamically change this span to 3 instead of two than this is what i get:

enter image description here

Bottom line is, what i am trying to achieve here is to have row area which is not expanding for each column but only where it is needed as it is for text area, the height of normal text-input is 45px and the height of textarea can vary per rows like 45px, 64px, 83px, 102px, 125px..., Can i somehow dinamically set this spaning based on textarea height, or what can i do to achieve independent columns here? Also there is bunch of other cases with elements like checkbox with even less height which tend to break here because of this.


Solution

  • I would implement this with nested grids. The outer grid manages the three columns, but has a single row, so a total of three cells. Each cell in this grid then contains a nested grid to manage its own labels and entry fields.

    enter image description here

    body {
      margin: 1em;
      background: #f6f6f6;
    }
    
    fieldset {
      display: grid;
      gap: 2em;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      border: 0;
      padding: 0;
    }
    
    .column {
      display: grid;
      gap: 1em;
      grid-template-columns: 2fr 5fr;
      align-content: start;
    }
    
    input, select, textarea {
      max-width: 100%;
      border: 1px solid #bbb;
      border-radius: 4px;
      box-shadow: 0 0 5px rgb(0 0 0 / 0.1);
    }
    
    select {
      appearance: none;
    }
    <fieldset>
      <div class="column">
        <label>Email&nbsp;*</label>
        <input type="email"/>
        <label>Phone&nbsp;*</label>
        <input type="text"/>
        <label>text64</label>
        <input type="text"/>
      </div>
    
      <div class="column">
        <label>List Numbers</label>
        <select></select>
        <label>Last Name</label>
        <textarea rows="5"></textarea>
        <label>First Name</label>
        <input type="text"/>
      </div>
    
      <div class="column">
        <label>fieldInt&nbsp;*</label>
        <input type="text"/>
        <label>dateCreated</label>
        <input type="text"/>
        <label>List Strings</label>
        <select></select>
        <label>isSubscribed</label>
        <input type="checkbox">
        <label>somelistdate</label>
        <select></select>
      </div>
    </fieldset>