在 CSS 网格周围的热潮中,我还没有看到太多关于新的 fr
CSS 长度单位的讨论(规范 中有介绍)。现在,浏览器对该功能的支持正在迅速提升,我认为现在是探索如何将它与我们新奇的布局引擎结合起来的时候了,因为使用它有很多好处;更易读和可维护的代码是切换到此单位的主要原因。
首先,让我们看看通常如何用 CSS 构建网格。在下面的示例中,我们创建了一个四列网格,每列宽度相等
<div class="grid">
<div class="column"> </div>
<div class="column"> </div>
<div class="column"> </div>
<div class="column"> </div>
</div>
.grid {
display: grid;
grid-template-columns: repeat(4, 25%);
grid-column-gap: 10px;
}
如果您以前从未在 grid-template-columns
属性后见过 repeat()
函数,那么让我向您介绍 CSS 网格最酷的功能之一!它实际上是一种简写,让我们能够更简洁地描述重复的值。我们也可以写 grid-template-columns: 25% 25% 25% 25%;
,但使用 repeat()
会更简洁,尤其是在您有更详细的宽度(比如 minmax()
表达式)时。
语法基本上是这样的
repeat(number of columns/rows, the column width we want);
但是,我们目前所做的事情实际上存在几个问题。
首先,为了使用这个很棒的 CSS 函数,我们不得不进行一点点数学运算。我们不得不思考 "网格的总宽度 (100%) 除以我们想要的列数 (4) 等于多少",这就得到了 25%。在本例中,数学运算非常简单,所以我们不用担心,但在更复杂的示例中,我们可以完全避免进行数学运算,让浏览器帮我们计算。我们确实可以使用 calc()
,所以我们可以写 repeat(4, calc(100% / 4)
,但这有点奇怪,而且还有一个问题…
第二个问题是溢出问题。因为我们将每列设置为 25%,并且 grid-column-gap
为 10px,这会导致网格元素 "超过 100%"。这与您从上面的代码中看到的布局方式并不一样,但这就是百分比的工作方式。我们在上面的代码中实际上说的是 "将每列设置为视窗宽度的 25% " 以及 "它们之间要有 10px 的间隔"。这是一个细微的差别,但会导致布局出现重大问题。
我们无意中导致了水平滚动
这就是 fr
单位可以帮助我们的地方。
fr
单位("分数")可用于定义网格,就像其他任何 CSS 长度(如 %
、px
或 em
)一样。让我们快速重构上面的代码,以使用这个独特的单位。
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 10px;
}
这看起来与上面的示例完全一样,因为在本例中,我们将四列中的每一列都设置为一个分数(正好是 1/4 或 25%)。但是!x 轴上不再有溢出了,因为将每列设置为 1fr 会自动将这 10px 计算在内,并将其从每列可用的总宽度中减去。
您可能会想,如果我基本上可以使用百分比或像素之类的单位,为什么我还要学习如何使用这个花哨的新 CSS 长度呢?好吧,让我们深入研究一个更复杂的 CSS 网格示例,来解释为什么 fr
是更好的选择。在一个新的示例中,假设我们想要一个固定宽度的左侧导航栏,然后是一个十二列的网格,它应该看起来像这样

这对于许多 UI 来说都是一个非常典型的场景,所以使用 fr
单位可以避免我们创建单独的网格 div 或使用 calc
搞乱代码。因为如果我们在上面的示例中不使用 fr
,那么我们就必须弄清楚以下问题
the width of each column = ((width of viewport - width of nav) / number of columns) * 1%
当然,这是可能的,但这读起来很痛苦,而且如果我们更改了导航栏的宽度,我们就必须再次进行这个愚蠢的计算。相反,fr
单位将所有这些操作简化为一行易于阅读的代码
.grid {
display: grid;
grid-template-columns: 250px repeat(12, 1fr);
grid-column-gap: 10px;
}
我们在这里做的是为第一列设置一个固定的像素宽度,然后创建十二个独立的列,每个列都设置为 "可用空间的一部分"(字面意思是规范中使用的表达方式)。但这没有复杂的计算或任何东西!它非常易于阅读,而且如果左侧导航栏的宽度发生变化,右侧的列的宽度也会自动调整。
只需付出一点努力,我们就可以使我们的界面在未来更容易维护,并确保我们的代码对于后面的开发人员来说更易于阅读。
其他人的信息
fr
单位的乐趣和力量来自将其与其他单位混合使用。想象一下一个固定的侧边栏和一个占据剩余空间的主内容区域:grid-template-columns: 200px 1fr;
很容易!
这里有一个 DigitalOcean 的示例,展示了如何很好地混合使用单位

Rachel Andrew 有一个关于 fr
的 视频
Anna Monus 有一个关于 fr
的 非常好的文章。

为 fr
单位欢呼!
太棒了!有人有 caniuse.com 的链接吗?这样我就可以查看当前的浏览器支持情况。
它目前(暂时?)仅在与网格布局一起使用时有效,所以:https://caniuse.cn/#feat=css-grid
使用
fr
获得列和行以达到黄金分割比例的简单经验法则是什么?我不确定是否讲得通,但 a:a+b 规则在视觉设计建议中经常出现,所以我很想知道fr
单位是否很容易实现这种比例目标。谢谢,我大约一个月前开始在管理工具中使用网格,
fr
单位对我来说有点模糊。这是一篇很棒的概述。fr
万岁!与 Flexbox 的比例缩放非常相似!
确实!我想知道如果 Flexbox 可以回到过去,他们是否会使用
fr
而不是无单位的数字,或者不会。我希望
fr
单位可以在除常用网格布局以外的其他上下文中使用。这个单位也可以替换flex-grow
属性,但更一般地说,它可以适用于其他情况。我认为
fr
单位是网格的 "flex-grow
属性",这是否不正确?设置flex-grow: 1
具有类似的效果 - 占据可用空间,但在其他flex-grow
元素之间进行分配。我很好奇是否有什么微妙的差别是我没有注意到的。关于网格单位的文章非常棒,很有趣,我期待着更多地使用它,甚至在生产环境中使用它 :)
我希望
fr
单位能够脱离网格布局,成为像px
、%
等一样的常用单位。有没有人已经采用了 CSS 网格?Opera Mini 的不支持是一个大问题吗?
您链接的规范中有一条注,指出
fr
不是 长度 单位,而是 灵活长度 单位,从技术上讲,它是一种不同的维度类型,专门用于网格布局。它不能通过calc()
函数与普通的长度单位组合使用(例如,像calc(1fr - 2em)
这样的东西是不允许的)。而且,CSSWG 成员确实承认 Flexbox 柔性因子实际上也是灵活长度,应该用
fr
来测量,而不是用纯数字来测量:https://wiki.csswg.org/ideas/mistakes。