css

Dynamic N-column grid with aligned columns with either Flex or Grid


I need to distribute fields in a grid format where the columns line up. The number of colums is unpredictable and depends on how many fields can fit, so I can't really use display:grid with a specific grid-template-columns: N N N...

On the other hand when I use Flex, the columns don't line up. The below Flex example shows arbitrary gap-based placement of each cell. The columns need to line up, and their number dynamically determined.

Is there a good solution?

.field-label {
    font-weight: bold;
    font-size: 1.2rem;
}

.field-value {
    font-size: 1.2rem;
}

.card-content-flex {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 20px;
 }
   <div class="card-content-flex">
      <div class="field">
         <div>
            <div class="field-label">Field</div>
            <div class="field-value">Value 1</div>
         </div>
      </div>
      <div class="field">
         <div>
            <div class="field-label">Field 2</div>
            <div class="field-value">Value ABSAHUASHIUS</div>
         </div>
      </div>
      <div class="field">
         <div>
            <div class="field-label">Field 3</div>
            <div class="field-value">Test Str Test Str Test Str Test Str</div>
         </div>
      </div>
      <div class="field">
         <div>
            <div class="field-label">Field 4</div>
            <div class="field-value">XYZ</div>
         </div>
      </div>
      <div class="field">
         <div>
            <div class="field-label">Field 5</div>
            <div class="field-value">ASDASSFDSFSDFSDFSDFSDFSD</div>
         </div>
      </div>
      <div class="field">
         <div>
            <div class="field-label">Field 6</div>
            <div class="field-value">asas asdasd asdasd</div>
         </div>
      </div>
      <div class="field">
         <div>
            <div class="field-label">Field 7</div>
            <div class="field-value">a</div>
         </div>
      </div>
      <div class="field">
         <div>
            <div class="field-label">Field 8</div>
            <div class="field-value">---</div>
         </div>
      </div>
       <div class="field">
         <div>
            <div class="field-label">Field 9</div>
            <div class="field-value">Long String Long String</div>
         </div>
      </div>
       <div class="field">
         <div>
            <div class="field-label">Field 10</div>
            <div class="field-value">X</div>
         </div>
      </div>
       <div class="field">
         <div>
            <div class="field-label">Field 11</div>
            <div class="field-value">Xsdfsfsdfsdfsf</div>
         </div>
      </div>
 </div>


Solution

  • CSS-Grid with auto-fit should do the trick, you just have to decide on a minimum column width.

    .field-label {
      font-weight: bold;
      font-size: 1.2rem;
    }
    
    .field-value {
      font-size: 1.2rem;
    }
    
    .card-content-flex {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
      justify-content: space-between;
      gap: 20px;
    }
    
    .field {
      word-break: break-word;
      outline: 1px solid grey;
    }
    <div class="card-content-flex">
      <div class="field">
        <div>
          <div class="field-label">Field</div>
          <div class="field-value">Value 1</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 2</div>
          <div class="field-value">Value ABSAHUASHIUS</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 3</div>
          <div class="field-value">Test Str Test Str Test Str Test Str</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 4</div>
          <div class="field-value">XYZ</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 5</div>
          <div class="field-value">ASDASSFDSFSDFSDFSDFSDFSD</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 6</div>
          <div class="field-value">asas asdasd asdasd</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 7</div>
          <div class="field-value">a</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 8</div>
          <div class="field-value">---</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 9</div>
          <div class="field-value">Long String Long String</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 10</div>
          <div class="field-value">X</div>
        </div>
      </div>
      <div class="field">
        <div>
          <div class="field-label">Field 11</div>
          <div class="field-value">Xsdfsfsdfsdfsf</div>
        </div>
      </div>
    </div>