首页 > 解决方案 > 浏览器无法将相对单位(百分比)应用于fr设置的空间

问题描述

问题详情

我写了这样的代码。fr在这里,由于widthheightobject-fit属性有效,图像应该被保留的空间传播。所以我认为第二个的文本.item会溢出。

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr;
  background: red;
  gap: 10px;
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="container">
  <div class="item">
    <img src="https://unsplash.it/450/450">
  </div>
  <div class="item">
    <img src="https://unsplash.it/450/450">
    text
  </div>
</div>

在 Firefox 中,这会导致文本用完,

在此处输入图像描述

Chrome 并非如此。

在此处输入图像描述

此外,将图像包装在一个div元素中而不是正好在网格项下方将解决问题。

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr;
  background: red;
  gap: 10px;
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="container">
  <div class="item">
    <div class="content">
      <img src="https://unsplash.it/450/450">
    </div>
  </div>
  <div class="item">
    <div class="content">
      <img src="https://unsplash.it/450/450">
      text
    </div>
  </div>
</div>

不相关但类似的文章

我发现了一个可能相关的问题,但我认为这个问题与我的问题无关,因为这个问题文本的源代码在 Firefox 和 Chrome 中可以正常工作。

不相关但相似的错误

我还查找了相关的 bug 票,但这些票已经被声明为已修复,可能与我的问题无关。

问题

  1. 这种差异是没有错误票证或未定义行为的错误吗?

  2. 如果这不是未定义的行为,那么正确的行为是什么?

标签: cssgoogle-chromefirefoxflexboxcss-grid

解决方案


如果这不是未定义的行为,那么正确的行为是什么?

我想说,Firefox 在这里做得正确,而 Chrome 是正确的。

首先,您可以将代码减少到以下内容,因为grid-template-rows: 1fr该行为不需要

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: red;
  gap: 10px;
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="container">
  <div class="item">
    <img src="https://unsplash.it/450/450">
  </div>
  <div class="item">
    <img src="https://unsplash.it/450/450">
    text
  </div>
</div>

然后您可以使用任何百分比值(小于或大于 100%),您将看到在我们有文本的第二种情况下,chrome 不会执行任何操作:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: red;
  gap: 10px;
}

img {
  width: 100%;
  height: 50%;
  object-fit: cover;
}
<div class="container">
  <div class="item">
    <img src="https://unsplash.it/450/450">
  </div>
  <div class="item">
    <img src="https://unsplash.it/450/450">
    text
  </div>
</div>

正如我在这里解释的那样,您正面临百分比高度的特定行为。默认情况下,百分比高度是相对于包含块的显式高度的,在我们的例子中,我们没有为行设置任何显式高度(1fr 不是显式的)。考虑到 CSS2 规范,我们应该不会auto

指定百分比高度。该百分比是相对于生成框的包含块的高度计算的。如果包含块的高度没有明确指定(即,它取决于内容高度),并且该元素不是绝对定位的,则该值计算为'auto'。 参考

Chrome 正在使用第二张图片执行此操作。它认为高度auto不是完全错误的。

在 CSS3 规范中,我们有另一个部分允许浏览器做更多的工作

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

然后你有一套复杂的规则,两个重要的部分是:

否则,百分比将根据包含块的大小进行解析。(包含块的大小不会根据框的结果大小重新解析因此内容可能会溢出或下溢包含块)。

还有一条带有注释的规则:

注意:在这种情况下,网格项目和弹性项目确实允许解决百分比。


为方便起见,浏览器会先忽略百分比高度,根据内容计算每个网格轨道的高度,得到以下内容:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: red;
  gap: 10px;
}

img {
  width: 100%;
  /*height: 100%;*/
  object-fit: cover;
}
<div class="container">
  <div class="item">
    <img src="https://unsplash.it/450/450">
  </div>
  <div class="item">
    <img src="https://unsplash.it/450/450">
    text
  </div>
</div>

然后考虑先前计算的网格轨道高度,我们解决百分比高度得到以下结果,我们不再重新计算轨道高度:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: red;
  gap: 10px;
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="container">
  <div class="item">
    <img src="https://unsplash.it/450/450">
  </div>
  <div class="item">
    <img src="https://unsplash.it/450/450">
    text
  </div>
</div>

文本将在逻辑上溢出,因为高度是由图像+文本定义的,我们告诉图像获取所有高度,使文本在外部并使图像填充所有空间。

使用任何百分比值都会给出相同的结果,即使图像 X% 的高度由 image+text 定义


设置显式高度将使两者的行为相同,因为我们没有复杂的计算,我们可以依赖规范的 CSS2 部分:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows:200px;
  background: red;
  gap: 10px;
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="container">
  <div class="item">
    <img src="https://unsplash.it/450/450">
  </div>
  <div class="item">
    <img src="https://unsplash.it/450/450">
    text
  </div>
</div>

添加一个额外的包装器将使高度auto在所有情况下都失败,因为浏览器处理这种情况变得更加复杂1

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: red;
  gap: 10px;
}

img {
  width: 100%;
  height: 958%;
  object-fit: cover;
}
<div class="container">
  <div class="item">
    <div>
      <img src="https://unsplash.it/450/450">
    </div>
  </div>
  <div class="item">
    <div>
      <img src="https://unsplash.it/450/450">
    </div>
    text
  </div>
</div>

添加height:100%到额外的包装器将恢复到以前的情况,并且可以再次解决高度问题:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: red;
  gap: 10px;
}

img {
  width: 100%;
  height: 50%;
  object-fit: cover;
}

.item>div {
  height: 100%;
}
<div class="container">
  <div class="item">
    <div>
      <img src="https://unsplash.it/450/450">
    </div>
  </div>
  <div class="item">
    <div>
      <img src="https://unsplash.it/450/450">
    </div>
    text
  </div>
</div>

在这种情况下,div 采用图像+文本定义的高度(文本将溢出),然后 div 内的图像将采用该高度的一半。


类似情况的相关问题:

https://stackoverflow.com/a/52137966/8620333

CSS Grid 中的 Chrome / Firefox 百分比高度差异

没有高度的网格间隙百分比

1:我无法给出确切的部分来解释为什么我们无法在这种情况下解决。


推荐阅读