Why is flex-fill not creating equal width in bootstrap?

Bootstrap’s flex-fill is unfortunately a very bad class. It sets the following flex CSS properties:

flex: 1 1 auto;

This is equivalent to:

flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;

The grow and shrink values are fine. This is what makes the boxes share the available space evenly. The auto flex-basis value however is not good:

The flex-basis is what defines the size of that item in terms of the space it leaves as available space. The initial value of this property is auto — in this case the browser looks to see if the items have a size. […]

If the items don’t have a size then the content's size is used as the flex-basis. This is why when we just declare display: flex on the parent to create flex items, the items all move into a row and take only as much space as they need to display their contents.

So flex-basis: auto makes the boxes have the width that the content needs. And only then, the growing and shrinking is applied to fill the remaining size of the container.

If you take a look at the output from your example, this is what you can see:

Measured widths of the whitespace

The columns are obviously not of the same width, but those blue boxes, which is the whitespace in each flex item, they all have the same width. So what is evened out is the remaining space, without taking the content into account.

Of course, this is rarely what you want to do. The most common thing to do with a flex box is to make all items have the same width. Without bootstrap, you would just do flex: 1 for this, which is the shorthand for flex: 1 1 0;

.flex-even {
  flex: 1;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>

<div class="d-flex">
  <div class="flex-even">Item</div>
  <div class="flex-even">Another</div>
  <div class="flex-even">Last item</div>
</div>

Unfortunately, that is not what the Bootstrap authors made their flex-fill to be. And to make matters worse, the example they are showing is using the same content in every flex item, so you don’t actually see that behavior. There’s also an issue about this, which may eventually clear up this misunderstanding in the docs.

Bottom line though: Bootstrap has no built-in flex: 1 class (at least to my knowledge), so you’re best off creating one for your own. It’s definitely the more useful “flex-fill”.