Search code examples
htmlcssflexboxwidthdisplay

CSS: What are the behavior rules for a "width: auto" container with inline-flex?


I was trying to create a list / table view with dynamic width using flexbox, and encountered a behavior I couldn't really wrap my head around. The result I'm trying to achieve is a width that fits the content of the list, at its' widest point.

.main {
  width: auto;
  background: rgb(233, 148, 148);
  display: inline-flex;
  flex-wrap: wrap;
}

.container {
  display: flex;
  width: 100%;
}

.label,
.value {
  flex: 1;
  padding: 4px;
}

.label {
  text-align: end;
  border-right: 2px solid red;
}

.value {
  text-align: start;
}
<div>
  <div class="main">
    <div class="container">
      <div class="label">Some Label</div>
      <div class="value">Some value</div>
    </div>
    <div class="container">
      <div class="label">Some label 2</div>
      <div class="value">Other val</div>
    </div>
    <div class="container">
      <div class="label">Third label</div>
      <div class="value">
        <div>N/A</div>
      </div>
    </div>
  </div>
</div>

What it boils down to, is that the width seems to be determined by the total characters count, and not the widest point, as I would expect. You can edit the HTML and remove the N/A, for example, and the width will decrease.

When I switch to display: inline-block with white-space: nowrap, the width is as expected, but the "columns" are not aligned.

.main {
  width: auto;
  background: rgb(233, 148, 148);
  display: inline-block;
  white-space: nowrap;
}

.container {
  display: flex;
  width: 100%;
}

.label,
.value {
  flex: 1;
  padding: 4px;
}

.label {
  text-align: end;
  border-right: 2px solid red;
}

.value {
  text-align: start;
}
<div>
  <div class="main">
    <div class="container">
      <div class="label">Some Label</div>
      <div class="value">Some value</div>
    </div>
    <div class="container">
      <div class="label">Some label 2</div>
      <div class="value">Other val</div>
    </div>
    <div class="container">
      <div class="label">Third label</div>
      <div class="value">
        <div>N/A</div>
      </div>
    </div>
  </div>
</div>

What causes the large width to occur when the display is inline-flex? Is there a way to get the behavior I'm trying to achieve? I know it can probably be resolved with display: grid, but I'm looking for a simpler solution.


Solution

  • I know it can probably be resolved with display: grid, but I'm looking for a simpler solution.

    It might be difficult if you do not handle the grid-layout fine enough yet, but it looks not that much complicated if you use the grid system ;)

    For the width, look at max-content.

    simple example:

    .main {
      width: max-content;
      background: rgb(233, 148, 148);
    }
    
    .container {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
    }
    
    .label,
    .value {
      padding: 4px;
    }
    
    .label {
      text-align: end;
      border-right: 2px solid red;
    }
    
    .value {
      text-align: start;
    }
    <div>
      <div class="main">
        <div class="container">
          <div class="label">Some Label</div>
          <div class="value">Some value</div>
        </div>
        <div class="container">
          <div class="label">Some label 2</div>
          <div class="value">Other val</div>
        </div>
        <div class="container">
          <div class="label">Third label</div>
          <div class="value">
            <div>N/A</div>
          </div>
        </div>
      </div>
    </div>


    In the past ,before flex & grid , display would use the table-layout.

    .main {
          display:table;
          background: rgb(233, 148, 148);
        }
      .container {
        display: table-row;
      }
      .label, .value {
        padding: 4px;
        display:table-cell;
      }
      .label {
        text-align: end;
        border-right: 2px solid red;
      }
      .value {
        text-align: start;
      }
    <div>
      <div class="main">
        <div class="container">
          <div class="label">Some Label</div>
          <div class="value">Some value</div>
        </div>
        <div class="container">
          <div class="label">Some label 2</div>
          <div class="value">Other val</div>
        </div>
        <div class="container">
          <div class="label">Third label</div>
          <div class="value">
            <div>N/A</div>
          </div>
        </div>
      </div>
    </div>