当子元素的宽度取决于父元素,而父元素的宽度又取决于子元素时,浏览器如何计算宽度?

3

我在我的React应用程序上遇到各种故障、奇怪的渲染工件等问题,想知道从浏览器的角度来看,定义尺寸的方式是如何工作的。

假设我有一个网格显示,其中有一个 div 元素,它具有 grid-template-columns: 1fr auto 1fr,并且一个子 div 元素具有跨越父级网格中的 auto 区域的列范围 grid-column: 2 / 3

据我所知,网格模板列中的值 auto 定义了要根据其内容调整大小的列。

现在,让我们添加一个 img,将 max-width 设置为 100% - 换句话说,我们不想超过父容器的大小。

但是,父容器的宽度是由 auto 规则确定的 - 那么浏览器怎么能让子元素知道占满100%呢?

示例:

.box {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  background-color: lightblue;
}

.box>div {
  border: 1px solid red;
  grid-column: 2 / 3;
  margin: 10px 10px 0px;
}
<div class="box">
  <div style="">
    <img src="https://via.placeholder.com/800" style="max-width:100%">
  </div>
</div>

1个回答

3
为了解释这个问题,我会从一个更简单的例子开始,它将产生相同的输出:

<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>

我们有一个内联块元素,因此它的宽度取决于其内容和使用max-width:100%(或width:100%),会给我们带来奇怪的结果。
要理解这一点,我们需要参考规范,更准确地说是百分比尺寸部分,其中我们可以读到:
“有时候,百分比大小的盒子所在的包含块的大小取决于盒子本身的内在大小贡献,从而创建一个循环依赖。当计算这样一个盒子的内在大小贡献时(包括任何基于内容的自动最小大小的计算),特殊地解决了一个循环百分比——即,一个百分比值,它将根据包含块大小解析出一个依赖该百分比的包含块大小。”
我们的盒子是图片,包含块是内联块div。图片是替换元素,因此我们需要遵循(b)和(c)来确定最大内容贡献最小内容贡献
同样地,如果该盒子被替换,则将包含循环百分比表达式的任何最大尺寸属性或首选尺寸属性的整个值仅视为该属性的初始值,用于计算盒子的最大内容贡献

max-width/width设置为auto将保持最大内容贡献不变(在我们的例子中为1000px)。改变的是最小内容贡献:

如果该盒子被替换,则将任何最大尺寸属性或首选尺寸属性(宽度/最大宽度/高度/最大高度)中的循环百分比解析为零,在计算相应轴上的最小内容贡献时

因此,图像的最小内容贡献将变为0,而不再是基于其固有尺寸的初始最小内容贡献1000px(相关资料:https://www.w3.org/TR/css-sizing-3/#intrinsic-sizes),这就是所有技巧的关键!

现在我们的内联块是一个收缩适应元素,以下算法适用:
然后收缩适应宽度为:min(max(首选最小宽度,可用宽度),首选宽度)ref 图像的贡献将从01000px变化,因此浏览器将选择避免任何溢出的值(可用宽度部分),并且不大于1000pxmin部分)。
如果不使用百分比,则图像的最小内容为1000px,因此浏览器必须使用1000px1000px之间的值作为首选最小宽度,这将使div具有图像的内在大小宽度。
所有这些只是计算div宽度。在此之后,我们将计算宽度视为百分比值的参考。
我们还可以考虑不同的值,逻辑将是相同的:

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>


由于您的列被设置为“auto”,这意味着它的大小基于其内容,并且也是图像的包含块,因此上述逻辑也适用于您的代码。

1
既然你问了,我认为这一切看起来都是正确的,并且非常严谨。 - Alohci
是的,在CSS2.1中,这种行为明确地没有定义。:https://www.w3.org/TR/CSS2/visudet.html#x9“如果包含块的宽度取决于此元素的宽度,则在CSS 2.1中,结果布局未定义。” - Kaiido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接