当孩子依赖父母,父母依赖孩子时,浏览器如何计算宽度

Posted

技术标签:

【中文标题】当孩子依赖父母,父母依赖孩子时,浏览器如何计算宽度【英文标题】:How do browsers calculate width when child depends on parent, and parent's depends on child's 【发布时间】:2020-11-10 02:07:06 【问题描述】:

我在我的 React 应用程序中遇到了各种故障、奇怪的渲染工件等等,我想知道从浏览器的角度定义维度的工作方式。

假设我有一个网格显示,有一个 div 具有 grid-template-columns: 1fr auto 1fr 和一个子 div 具有跨度 grid-column: 2 / 3 - 换句话说,跨越父网格的 auto 区域。

据我了解,网格模板列中的值 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】:

为了解释这一点,我将从一个更简化的示例开始,它会产生相同的输出:

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

我们有一个inline-block 元素,所以它的宽度取决于它的内容,使用max-width:100%(或width:100%)会给我们带来奇怪的结果。

要理解这一点,我们需要参考规范,更准确地说是Percentage Sizing 部分,我们可以阅读:

有时,百分比大小的盒子的包含块的大小取决于盒子本身的内在尺寸贡献,从而产生循环依赖 .当计算这样一个盒子的内在尺寸贡献时(包括任何基于内容的自动最小尺寸的计算),一个循环百分比 - 即一个百分比值,它将针对本身取决于该百分比的包含块大小进行解析 - 是特别解决:

我们的盒子是图片,包含块是inline-block div。图片是替换元素,所以我们需要按照 (b) 和 (c) 来识别 最大内容贡献最小内容贡献

b.同样,如果盒子被替换,那么任何最大尺寸属性或首选尺寸属性的整个值都被处理为包含循环百分比的表达式以计算盒子的最大内容贡献 仅作为该属性的初始值

max-width/width 视为自动将保持最大内容贡献相同(在我们的例子中为1000px)。将改变的是 min-content 贡献:

c。如果盒子被替换,任何最大尺寸属性或首选尺寸属性(width/max-width/height/max-height)的值中的循环百分比,在计算 min-content 贡献时解决为零对应的轴

因此图像的最小内容贡献将变为0,不再是1000px,这是基于其内在维度的初始最小内容贡献(相关:https://www.w3.org/TR/css-sizing-3/#intrinsic-sizes),所有技巧都在这里!

现在我们的 inline-block 是一个收缩到适合的元素,下面的算法适用:

那么收缩到适合的宽度是:min(max(preferred minimum width, available width), preferred width)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,这意味着它的大小取决于其内容,也是图像的包含块。

【讨论】:

既然你问了,这一切对我来说都是正确的,并且经过严格的覆盖。 是的,并且在 CSS2.1 中该行为是明确未定义的。:w3.org/TR/CSS2/visudet.html#x9 "如果包含块的宽度取决于此元素的宽度,则结果布局在 CSS 2.1 中未定义。"跨度>

以上是关于当孩子依赖父母,父母依赖孩子时,浏览器如何计算宽度的主要内容,如果未能解决你的问题,请参考以下文章

如何仅使用 CSS 使孩子自动适应父母的宽度?

防止孩子增加父母的宽度[重复]

角。使孩子 100% 宽度的 flex 父母

当父母和孩子有相同的数据时,如何使用 Alamofire 解析数据?

颤动中从孩子到父母的回调

如何从子类访问父类数据成员,当父母和孩子的日成员具有相同的名称时