CSS Grid经过这么多年的发展已经越来越受人青眯了,到目前为止支持率得到近88%的比例。经过这么多年的跟踪和学习,对CSS Grid的特性也是略有所知,但还未达到完全的融汇贯通。因为它有很多的特性,而且这些特性对于CSSer来说很多都是新的概念,比如我们今天要说的分数单位fr
就是一个新东东。那么这篇文章,咱们就来一起看看这个特性有什么特性,给我们又能带来什么好处。感兴趣的同学,请继续往下阅读。
简介
在CSS Grid中可以使用任何长度单位来给网格轨道定义大小。比如在grid-template-columns
或grid-template-rows
可以使用px
、rem
、vw
、100%
等CSS单位来设置大小,除此之外,CSS网格还引入了另一个长度单位来帮助我们创建网格轨道大小。这个新单位就是我们今天要聊的fr
单位。大家喜欢把它称为分数单位。那么他究竟有什么作用呢?
在MDN是这样描述的:
新的
fr
单位代表网格容器中可用空间的一等份。
就从这样的描述或许还是会令人感到困惑。不用担心,我们继续往下阅读,我想可以帮你解惑的。
对比性思考
fr
是代表网格容器中可用空间的一等份,即1fr
。如果是2fr
那么就是把容器剩余的空间分成两等份。看到这里,是否会想起Flexbox布局中的flex
呢?比如我们有这样的一个示例:
<div class="flex">
<aside>Sidebar</aside>
<main>Main</main>
</div>
.flex {
width: 600px;
background: orange;
display: flex;
min-height: 50vh;
}
aside {
width: 200px;
background: #f36;
}
main {
margin-left: 20px;
background: #f63;
flex: 1;
}
效果如下:
可以看出,main
元素设置flex:1
时也占用了容器剩余的空间(600px - 200px - 20px = 380px
)。从浏览器的查看器中可以验证,计算是无误的:
在上面的示例中,我们再来变更一下,再添加一个侧边栏:
main {
flex: 2
}
aside:last-of-type {
flex: 1
}
使用浏览器再次验证我们的计算是不是正确的:
上图可以告诉我们答案,和我们最初想的是一样的。Flexbox中的flex
也可以把Flexbox容器剩余的容器进行平分。具体平分多少等份需要根据Flexbox容器子元素,也就是Flex项目使用了几等份。比如上例中的main
使用了flex:2
,第二个aside
使用了flex:1
。也就是说,此例中把Flexbox容器剩余的空间分成了三等份,其中main
占三分之二,剩余的三分之一给了右侧的aside
元素。
Flexbox中的
flex
属性是flex-basis
、flex-shrink
和flex-grow
三个属性的简写属性,而其盒模型的计算是相当复杂的,感兴趣的可以阅读《深入理解 Flexbox 布局以及计算》一文。
正因为如此,所以flex
属性常用来把一个容器分成均匀的等份,特别是在移动端的时候,制作Tabbar效果,特为显著:
如果我们用CSS Grid来实现上图的效果。其实就是一个一行五列的网格,并且每列都等宽:
<footer>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</footer>
footer {
width: 750px;
display: grid;
grid-template-columns: 20% 20% 20% 20% 20%;
}
在fr
单位还没出来之前,大家可能会想到的是百分比单位,正如上面的代码所示。也正因为,列表项刚好能被整除,所以效果接近完美:
大家看到示例了,我们有写了五个20%
,其实在CSS Grid布局中有一个函数repeat()
可以让我少写重复的代码:
grid-template-columns: repeat(5, 20%)
我们还是回到主题上来。上面的示例中列表项可以被整除,那么问题来了,如果容器不能被列表项整除,比如列表项是3
这样的。那么结果就会差强人意了。或者又说,如果列表项之间有间距(比如说10px
),使用百分比相对而言就要麻烦了。因为此时按计算,每个列表项的宽度就变成了(100% - 10px * 4) / 5
。如果知道容器的值,我们换成固定值也好计算,比如(750px - 4 * 10) / 5 = 142px
:
footer {
display: grid;
grid-template-columns: repeat(5, 142px);
grid-gap: 10px;
}
在不知道容器具体宽度值,比如开始所说的百分比,那么就需要借且calc()
函数帮我们,calc((100% - 4 * 10px) / 5)
:
footer {
display: grid;
grid-template-columns: repeat(5, calc((100% - 4 * 10px) / 5));
grid-gap: 10px;
}
得到的效果和上图将是一样的。
fr
登场
正如前面所示,calc(100% - 4 * 10px)
其实就是计算容器扣除网格间距(4 * 10px = 40px
)所剩下的容器空间。也就可以想象像成:
1fr = calc(100% - 4 * 10px)
而我们示例有五个列表项,每个列表项都是均等的,所以将会分成五等份,即可五个1fr
,用repeat()
的话可以表示成repeat(5, 1fr)
:
footer {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 10px;
}
得到的效果将是一致的:
此时我们要去掉grid-gap
,那么就得到我们想要的均分列表项,也最终得到我们想要的效果:
简单的用几张图来向大家展示fr
在CSS Grid中是如何计算的。
现在我们再来看一个不是均分的:
#app {
display: grid;
grid-template-columns: 3fr repeat(4, 1fr) 2fr;
grid-gap: 20px;
max-width: 1200px;
}
上面我们看到的都是使用fr
为单位的网格项。其实还可以和auto
、%
和px
等混合在一起使用。比如:
#app {
display: grid;
grid-template-columns: auto repeat(5, 1fr);
grid-gap: 20px;
width: 1200px;
}
再来看一个%
的:
#app {
display: grid;
grid-template-columns: 30% repeat(4, 1fr) 20%;
grid-gap: 20px;
width: 1200px;
}
除些之外,还可以多种混合使用:
总结
文章中介绍了fr
单位如何使用以及它是如何计算的。从上面的示例中可以看出,fr
单位非常的强大。虽然很强大,但该单位可以说是CSS Grid中的专有的,在别的地方使用是无效的,好比flex:1
只能在Flexbox布局中使用。另外fr
使用的时候,可以结合CSS其他单位一起使用。
如果你对fr
单位有更深入的了解,欢迎在下面的评论中与我们一起分享。