为什么 grid-gap 会导致溢出?

Why does grid-gap cause an overflow?

为什么我在以下代码段中的 X 轴上有溢出?

一旦我在我的 .body 网格容器上应用 grid-gap: 10px,就会产生溢出。

div:not(.header):not(.body):not(.row) {
  border: 1px solid grey;
}

.header {
  margin-top: 20px;
  display: grid;
  grid-gap: 10px;
  grid-template-areas: "header-left header-right-up" "header-left header-right-down";
  grid-template-rows: 40px 40px;
  grid-template-columns: minmax(50px, 200px) auto;
}

.header-left {
  grid-area: header-left;
}

.header-right-up {
  grid-area: header-right-up;
}

.header-right-down {
  grid-area: header-right-down;
}

.body {
  margin-top: 20px;
  display: grid;
  grid-template-columns: 25% 50% 25%;
  grid-auto-rows: 80px; 
  grid-gap: 10px;
}

.row-left {
}

.row-center {
}

.row-right {
}
<div class="header">
  <div class="header-left">image</div>
  <div class="header-right-up">content</div>
  <div class="header-right-down">long content</div>
</div>

<div class="body">
    <div class="row-left"></div>
    <div class="row-center"></div>
    <div class="row-right"></div>

    <div class="row-left"></div>
    <div class="row-center"></div>
    <div class="row-right"></div>

    <div class="row-left"></div>
    <div class="row-center"></div>
    <div class="row-right"></div>
  </div>
</div>

https://codepen.io/anon/pen/WdJExz?editors=1100

简答

因为列的宽度加上间隙的宽度大于 100%。


说明

您有一个 3 列网格容器 (.body):

grid-template-columns: 25% 50% 25%

这些列的总宽度为 100%。

然后您将在列(和行)之间添加间距:

grid-gap: 10px

这是 shorthand 用于:

grid-column-gap: 10px;
grid-row-gap: 10px;

所以这变成了宽度计算:

25% + 50% + 25% + 10px + 10px

因此,

100% + 20px > 100%, which results in an overflow condition

请注意,grid-*-gap 属性仅适用于网格项之间——从不适用于项与容器之间。这就是为什么我们计算两个网格间隙,而不是四个。

作为 解决方案,请尝试使用 fr 单位而不是百分比单位,这仅适用于免费 space。这意味着在应用任何 grid-gap 长度后 计算 fr 长度。

grid-template-columns: 1fr 2fr 1fr

div:not(.header):not(.body):not(.row) {
  border: 1px solid grey;
}

.header {
  margin-top: 20px;
  display: grid;
  grid-gap: 10px;
  grid-template-areas: "header-left header-right-up" "header-left header-right-down";
  grid-template-rows: 40px 40px;
  grid-template-columns: minmax(50px, 200px) auto;
}

.header-left {
  grid-area: header-left;
}

.header-right-up {
  grid-area: header-right-up;
}

.header-right-down {
  grid-area: header-right-down;
}

.body {
  margin-top: 20px;
  display: grid;
  grid-template-columns: 1fr 2fr 1fr; /* ADJUSTMENT */
  grid-auto-rows: 80px;
  grid-gap: 10px;
}

.row-left {}

.row-center {}

.row-right {}
<div class="header">
  <div class="header-left">image</div>
  <div class="header-right-up">content</div>
  <div class="header-right-down">long content</div>
</div>

<div class="body">
  <div class="row-left"></div>
  <div class="row-center"></div>
  <div class="row-right"></div>

  <div class="row-left"></div>
  <div class="row-center"></div>
  <div class="row-right"></div>

  <div class="row-left"></div>
  <div class="row-center"></div>
  <div class="row-right"></div>
</div>

revised codepen demo

此处有更多详细信息:

如果您想使用百分比或其他一些单位,还有另一种解决方案。 minmax() 函数的使用将允许列收缩以适应父容器并且不会导致溢出

解决方案如下所示:

grid-template-columns: minmax(auto, 25%) minmax(auto, 50%) minmax(auto, 25%);
gap: 10px;

有关 minmax() 函数的更多信息 here

如果您有固定数量的网格列,它们应该具有相同的宽度并使用 grid-gap,有一种方法可以做到:

display: grid;
grid-template-columns: repeat(4, calc(25% - 0.75em));
grid-gap: 1em;

在这种情况下,每行将有 4 个网格列,grid-gap 占用的总 space 为 3em。为了均匀分配溢出的space,将space除以网格列数。

3em / 4 = 0.75em

这使得所有网格列具有相同的宽度。

Codepen demo

回复晚了,但 100% 值得。

来自许多资源的总结。

  1. %
  2. 的用法

使用 % 计算的网格列未考虑间距(也称为间隙)。因此,您需要将添加的间隙的像素添加到计算中。所以 totalGridWidth = SUM(...%) + gutters = ~100% + gutters

  1. fr
  2. 的用法

上一个问题不会发生 (第 3 号例外。) 因为它包括计算免费 space 以及差距。所以计算如下:(free space - gutters) / 12 = 1fr 因此在这里你可以得到比率作为分数而不是部分作为百分比。

或者换句话说,最小公约数 (1fr = 25%):

grid-template-columns: 1fr 2fr 1fr;

  1. minmax(0,Xfr)
  2. 的用法

默认情况下,浏览器布局引擎使用此公式 Xfr 来计算 minmax(auto,Xfr),它依赖于您的项目的最小尺寸,以及这些项目或内部元素中的任何一个预计何时增长width:100% 之类的东西无限大,auto 参数仍然是情况 2。到 运行 有时会出现溢出的网格。为了防止这种情况,我们需要强制浏览器使用一种可以将元素缩小到实际最小值的方法,即 0px 要做到这一点,您需要使用 minmax(0,Xfr)X 作为所需的分数。

换句话说,对于您之前的案例:

grid-template-columns: minmax(0,1fr) minmax(0,2fr) minmax(0,1fr);

我知道这可能看起来太冗长了,但考虑到你这样的边缘情况,我们不能在这里使用 repeat(),无论如何,这将是你溢出问题的防弹。

您可以在我找到的这篇文章中阅读更多内容:

https://css-tricks.com/preventing-a-grid-blowout/

我也遇到了这个问题,对我有用的是将 grid-template-column: 50% 50%; 替换为 grid-template-column: auto 50%;