How do browsers calculate width when child depends on parent, and parent’s depends on child’s

To explain this, I will start with a more simplified example that will produce the same output:

<div style="display:inline-block">
  <img src="https://via.placeholder.com/1000x100">
</div>

<div style="display:inline-block">
  <img src="https://via.placeholder.com/1000x100" style="max-width:100%">
</div>

<div style="display:inline-block">
  <!-- even a big explicit width specified won't change the behavior -->
  <img src="https://via.placeholder.com/1000x100" style="wdith:2000px;max-width:100%">
</div>

<div style="display:inline-block">
  <img src="https://via.placeholder.com/1000x100" style="width:100%">
</div>

We have an inline-block element so its width depend on its content and the use of max-width:100% (or width:100%) will give us the strange result.

To understand this, we need to refer to the specification and more precisely Percentage Sizing section where we can read:

Sometimes the size of a percentage-sized box’s containing block depends on the intrinsic size contribution of the box itself, creating a cyclic dependency. When calculating the intrinsic size contribution of such a box (including any calculations for a content-based automatic minimum size), a cyclic percentage—that is, a percentage value that would resolve against a containing block size which itself depends on that percentage—is resolved specially:

Our box is the image and the containing block is the inline-block div. The image is a replaced element so we need to follow the (b) and (c) to identify the max-content contribution and the min-content contribution

b. Likewise, if the box is replaced, then the entire value of any max size property or preferred size property specified as an expression containing a percentage that is cyclic is treated for the purpose of calculating the box’s max-content contributions only as that property’s initial value.

Considering max-width/width as auto will keep the max-content contribution the same (1000px in our case). What will change is the min-content contribution:

c. If the box is replaced, a cyclic percentage in the value of any max size property or preferred size property (width/max-width/height/max-height), is resolved against zero when calculating the min-content contribution in the corresponding axis.

So the min-content contribution of the image will become 0 and no more 1000px which was the initial min-content contribution based on its intrinsic dimension (related: https://www.w3.org/TR/css-sizing-3/#intrinsic-sizes) and all the trick is here!

Now our inline-block is a shrink-to-fit element and the following algorithm apply:

Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width). ref

the contribution of the image will vary from 0 to 1000px so the browser will pick the value that will avoid any overflow (the available width part) and not bigger than 1000px (the min part)

Without the use of percentage the min-content of the image was 1000px so the browser is obliged to use a value between 1000px and 1000px as preferred minimum width which will give the div the intrinsic size width of the image.

All this is only the calculation of the div width. After this, we consider the calculated width as a reference for our percentage value.

We can also consider different value and the logic will be the same:

div {
  border:2px solid red;
  margin:5px;
}
<div style="display:inline-block">
  <img src="https://via.placeholder.com/1000x100">
</div>

<div style="display:inline-block">
  <img src="https://via.placeholder.com/1000x100" style="max-width:80%">
</div>

<div style="display:inline-block">
  <img src="https://via.placeholder.com/1000x100" style="width:50%">
</div>

The above logic apply the same way to your code since your column is set to auto which means that its size is based on its content and is also the containing block of the image.

Leave a Comment