百分比和fr单位的区别
The difference between percentage and fr units
我正在研究 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;
}
<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>
如您所见,由于 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;
}
<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>
用于寻找答案的资源:
如果有人能解释为什么百分比宽度会产生如此大的差异,那就太好了。
According to this part of the spec fr 单位不是长度,因此它在确定布局引擎中可用的空闲 space 数量后得到 "calculated"。
您在第一个示例中创建的变量是计算的一部分(宽度的 100% 除以 12),因此它会在传递给布局引擎之前运行计算。
当我说布局引擎时,我将其用作比喻,不想让人们混淆浏览器完成的渲染过程。我只是想说,在你的第一个例子中,你展示了一系列插入浏览器以开始渲染过程的数字,而在你的第二个例子中,你展示了更多浏览器可以使用的 algorithm/function进行布局。
fr
fr
单元仅适用于容器中的空闲 space。
所以在你的代码中:
grid-template-columns: repeat(12, 1fr);
...容器中空闲的space平均分配给12列
因为列只处理 free space,所以 grid-column-gap
不是一个因素。在确定 fr
长度 (spec reference) 之前从容器宽度中减去它。
浏览器的计算方式如下:
(free space - gutters) / 12 = 1fr
%
当您使用百分比时...
grid-template-columns: repeat(12, calc(100% / 12));
...容器分为12列,每列宽度为8.33333%。这是一个实际长度,与 fr
单元不同,它只处理自由 space.
列长度和网格间距都计入宽度。
浏览器的计算方式如下:
8.33333% * 12 = 100%
+
11 * 10px = 110px
明显溢出。
(注意:grid-*-gap
属性仅适用于网格项之间——从不适用于项与容器之间。这就是网格间隙的数量为 11 而不是 13 的原因。)
这个有效:
grid-template-columns: repeat(12, calc(8.3333% - 9.1667px));
分解为:
12 列
每列的宽度由容器的整个宽度 (100%
) 除以 12
确定
100% / 12 = 8.3333% (individual column width)
然后减去列间距(有11个)
10px * 11 = 110px (total width of column gaps)
110px / 12 = 9.1667px (amount to be deducted from each column)
.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; }
<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>
回复晚了,但 100% 值得。
我必须向 Michael Benjamin 添加一件重要的事情,在 3.
中指定
包含收集到的所有案例的摘要。
1.与 %
一起使用
用 %
计算的网格列没有考虑间距(又名间隙)。因此,您需要将添加的间隙的像素添加到计算中。所以 totalGridWidth = SUM(...%) + gutters = ~100% + gutters
2。与 fr
一起使用
上一个问题不会发生 (第 3 号例外。) 因为它包括计算免费 space 以及差距。所以计算如下:(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)
和 X
作为所需的分数。
或者换句话说,对于您之前的案例:
grid-template-columns: repeat(12, minmax(0,1fr));
这将是解决您的溢出问题的防弹药。
您可以在我找到的这篇文章中阅读更多内容:
我正在研究 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;
}
<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>
如您所见,由于 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;
}
<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>
用于寻找答案的资源:
如果有人能解释为什么百分比宽度会产生如此大的差异,那就太好了。
According to this part of the spec fr 单位不是长度,因此它在确定布局引擎中可用的空闲 space 数量后得到 "calculated"。
您在第一个示例中创建的变量是计算的一部分(宽度的 100% 除以 12),因此它会在传递给布局引擎之前运行计算。
当我说布局引擎时,我将其用作比喻,不想让人们混淆浏览器完成的渲染过程。我只是想说,在你的第一个例子中,你展示了一系列插入浏览器以开始渲染过程的数字,而在你的第二个例子中,你展示了更多浏览器可以使用的 algorithm/function进行布局。
fr
fr
单元仅适用于容器中的空闲 space。
所以在你的代码中:
grid-template-columns: repeat(12, 1fr);
...容器中空闲的space平均分配给12列
因为列只处理 free space,所以 grid-column-gap
不是一个因素。在确定 fr
长度 (spec reference) 之前从容器宽度中减去它。
浏览器的计算方式如下:
(free space - gutters) / 12 = 1fr
%
当您使用百分比时...
grid-template-columns: repeat(12, calc(100% / 12));
...容器分为12列,每列宽度为8.33333%。这是一个实际长度,与 fr
单元不同,它只处理自由 space.
列长度和网格间距都计入宽度。
浏览器的计算方式如下:
8.33333% * 12 = 100%
+
11 * 10px = 110px
明显溢出。
(注意:grid-*-gap
属性仅适用于网格项之间——从不适用于项与容器之间。这就是网格间隙的数量为 11 而不是 13 的原因。)
这个有效:
grid-template-columns: repeat(12, calc(8.3333% - 9.1667px));
分解为:
12 列
每列的宽度由容器的整个宽度 (
确定100%
) 除以 12100% / 12 = 8.3333% (individual column width)
然后减去列间距(有11个)
10px * 11 = 110px (total width of column gaps) 110px / 12 = 9.1667px (amount to be deducted from each column)
.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; }
<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>
回复晚了,但 100% 值得。
我必须向 Michael Benjamin 添加一件重要的事情,在 3.
中指定包含收集到的所有案例的摘要。
1.与 %
用 %
计算的网格列没有考虑间距(又名间隙)。因此,您需要将添加的间隙的像素添加到计算中。所以 totalGridWidth = SUM(...%) + gutters = ~100% + gutters
2。与 fr
上一个问题不会发生 (第 3 号例外。) 因为它包括计算免费 space 以及差距。所以计算如下:(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)
和 X
作为所需的分数。
或者换句话说,对于您之前的案例:
grid-template-columns: repeat(12, minmax(0,1fr));
这将是解决您的溢出问题的防弹药。
您可以在我找到的这篇文章中阅读更多内容: