CSS `fr` 单位简介

Avatar of Robin Rendle
Robin Rendle 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费积分!

在 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 长度(如 %pxem)一样。让我们快速重构上面的代码,以使用这个独特的单位。

.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 单位欢呼!