CSS网格布局中百分比和fr单位之间的差异

Mor*_*eus 15 css css3 css-grid

我正在玩CSS网格布局,并遇到了一个我无法找到答案的问题.

请考虑以下示例:

:root {
  --grid-columns: 12;
  --column-gap: 10px;
  --row-gap: 10px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), calc(100% / var(--grid-columns)));
  grid-column-gap: var(--column-gap);
  grid-row-gap: var(--row-gap);
  justify-content: center;		
} 

[class*=l-] {
  border: 1px solid red;
}

.l-1 {
  grid-column-start: span 1;		
}

.l-2 {
  grid-column-start: span 2;
}

.l-3 {
  grid-column-start: span 3;
}

.l-4 {
  grid-column-start: span 4;
}

.l-5 {
  grid-column-start: span 5;
}

.l-6 {
  grid-column-start: span 6;
}

.l-7 {
  grid-column-start: span 7;
}

.l-8 {
  grid-column-start: span 8;
}

.l-9 {
  grid-column-start: span 9;
}

.l-10 {
  grid-column-start: span 10;
}

.l-11 {
  grid-column-start: span 11;
}

.l-12 {
  grid-column-start: span 12;
}
Run Code Online (Sandbox Code Playgroud)
<div class="grid">
  <div class="l-6">Column 1</div>
  <div class="l-6">Column 2</div>
  <div class="l-3">Column 3</div>
  <div class="l-4">Column 4</div>
  <div class="l-3">Column 5</div>			
  <div class="l-2">Column 6</div>
  <div class="l-1">Column 7</div>
  <div class="l-10">Column 8</div>
  <div class="l-1">Column 9</div>
  <div class="l-5">Column 10</div>
  <div class="l-5">Column 11</div>
  <div class="l-2">Column 12</div>
</div>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,由于设置的百分比宽度,列会超出屏幕宽度calc(100% / var(--grid-columns)).

但如果我使用fr单位,它完美地运作:

:root {
  --grid-columns: 12;
  --column-gap: 10px;
  --row-gap: 10px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), 1fr); 
  grid-column-gap: var(--column-gap);
  grid-row-gap: var(--row-gap);
  justify-content: center;		
}

[class*=l-] {
  border: 1px solid red;
}

.l-1 {
  grid-column-start: span 1;		
}

.l-2 {
  grid-column-start: span 2;
}

.l-3 {
  grid-column-start: span 3;
}

.l-4 {
  grid-column-start: span 4;
}

.l-5 {
  grid-column-start: span 5;
}

.l-6 {
  grid-column-start: span 6;
}

.l-7 {
  grid-column-start: span 7;
}

.l-8 {
  grid-column-start: span 8;
}

.l-9 {
  grid-column-start: span 9;
}

.l-10 {
  grid-column-start: span 10;
}

.l-11 {
  grid-column-start: span 11;
}

.l-12 {
  grid-column-start: span 12;
}
Run Code Online (Sandbox Code Playgroud)
<div class="grid">
  <div class="l-6">Column 1</div>
  <div class="l-6">Column 2</div>
  <div class="l-3">Column 3</div>
  <div class="l-4">Column 4</div>
  <div class="l-3">Column 5</div>			
  <div class="l-2">Column 6</div>
  <div class="l-1">Column 7</div>
  <div class="l-10">Column 8</div>
  <div class="l-1">Column 9</div>
  <div class="l-5">Column 10</div>
  <div class="l-5">Column 11</div>
  <div class="l-2">Column 12</div>
</div>
Run Code Online (Sandbox Code Playgroud)

用于查找答案的资源:

如果有人能解释为什么百分比宽度会产生这样的差异,那将会很棒.

Mic*_*l_B 30

fr

fr装置仅适用于容器中的自由空间.

所以在你的代码中:

grid-template-columns: repeat(12, 1fr);
Run Code Online (Sandbox Code Playgroud)

...容器中的自由空间在12列中平均分配.

由于列只处理自由空间,grid-column-gap因此不是一个因素.fr在确定长度之前从容器宽度中减去它(规格参考).

以下是浏览器的计算方法:

(free space - gutters) / 12  = 1fr
Run Code Online (Sandbox Code Playgroud)

%

当你使用百分比时......

grid-template-columns: repeat(12, calc(100% / 12));
Run Code Online (Sandbox Code Playgroud)

...容器分为12列,每列宽8.33333%.这是一个实际长度,不像fr单位,只涉及自由空间.

柱长和网格间隙都考虑在宽度中.

以下是浏览器的计算方法:

8.33333% * 12 = 100%
         +
11 * 10px     = 110px
Run Code Online (Sandbox Code Playgroud)

有明显的溢出.

(注意:grid-*-gap属性仅适用于网格项之间 - 从不在项目和容器之间.这就是为什么网格间隙的数量是11,而不是13.)

这有效:

grid-template-columns: repeat(12, calc(8.3333% - 9.1667px));
Run Code Online (Sandbox Code Playgroud)

其中细分为:

.grid {
  display: grid;
  grid-template-columns: repeat(12, calc(8.3333% - 9.1667px));
  grid-column-gap: 10px;
  grid-row-gap: 10px;
  justify-content: center;
}

.l-1 { grid-column-start: span 1; }
.l-2 { grid-column-start: span 2; }
.l-3 { grid-column-start: span 3; }
.l-4 { grid-column-start: span 4; }
.l-5 { grid-column-start: span 5; }
.l-6 { grid-column-start: span 6; }
.l-7 { grid-column-start: span 7; }
.l-8 { grid-column-start: span 8; }
.l-9 { grid-column-start: span 9; }
.l-10 { grid-column-start: span 10; }
.l-11 { grid-column-start: span 11; }
.l-12 { grid-column-start: span 12; }
[class*=l-] { border: 1px solid red; }
Run Code Online (Sandbox Code Playgroud)
<div class="grid">
  <div class="l-6">Column 1</div>
  <div class="l-6">Column 2</div>
  <div class="l-3">Column 3</div>
  <div class="l-4">Column 4</div>
  <div class="l-3">Column 5</div>
  <div class="l-2">Column 6</div>
  <div class="l-1">Column 7</div>
  <div class="l-10">Column 8</div>
  <div class="l-1">Column 9</div>
  <div class="l-5">Column 10</div>
  <div class="l-5">Column 11</div>
  <div class="l-2">Column 12</div>
</div>
Run Code Online (Sandbox Code Playgroud)


Ign*_*tos 11

回复晚了,但 100% 值得。

我必须向迈克尔·本杰明补充一件重要的事情,如第 3 条所述。

总结所有收集到的案例。

1. 配合使用%

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

2. 配合使用fr

上一个问题不会发生(第 3 号例外),因为它包括计算可用空间以及间隙。因此计算如下:(free space - gutters) / 12 = 1fr因此在这里您可以获得分数形式的比率,而不是百分比形式的部分。

或者换句话说:

grid-template-columns: repeat(12, 1fr);

3. 配合使用minmax(0,Xfr)

默认情况下,浏览器布局引擎用于计算Xfr此公式minmax(auto,Xfr),该公式依赖于项目的最小大小,并且当任何这些项目或内部元素预计会无限期地增长时,诸如width:100%参数之auto类的事情仍然会使情况 2. 运行有时会出现溢出的网格。为了防止这种情况,我们需要强制浏览器使用一种可以缩小元素直到其真正最小值的方法,为此0px您需要使用minmax(0,Xfr)withX作为所需的分数。

或者换句话说,对于您之前的情况:

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

这将成为解决您的过多问题的防弹方案。

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

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


小智 5

根据规范的这一部分, fr 单位不是长度,因此在确定布局引擎内可用的可用空间量后“计算”它。

您在第一个示例中创建的变量是计算的一部分(100% 宽度并除以 12),因此它会在传递到布局引擎之前运行计算。

当我说布局引擎时,我将其用作隐喻,不想让人们对浏览器完成的渲染过程感到困惑。我只是想说,在您的第一个示例中,您呈现了一系列插入浏览器以开始渲染过程的数字,在第二个示例中,您呈现了更多浏览器可以用来制作的算法/函数它的布局。