使用CSS Grid实现瀑布流布局

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

自从多列布局,Flexbox布局和Grid布局得到浏览器支持之后,就可以使用这些特性来实现瀑布流的布局,但这些布局或多或少都存有一定的缺陷。前两天看到CSS 布局模块Level 3已经进入到 ED(Editor’s Draft)阶段,该规范就是为瀑布流布局而生的,这个模块中介绍了瀑布流布局,并且作为CSS网格容器的附加布局模式。接下来和大家一起来一探其究竟,另外在文章末尾顺便介绍了如何给不支持瀑布流布局的降级以及如何使用CSS Houdini来实现瀑布流布局。感兴趣的同学,请继续往下阅读。

什么是瀑布流布局

瀑布流布局是一种常见的Web布局模式。在一个容器中有很多项目(通常是图像或像文章的摘要),它们依次安排好照行内方向一个一个地放在列中。当它们移到下一行时,项目将移动到第一行较短(高度较低)项目所留下的空隙中。有点类似于我们生活中“砌砖”的方式:

这种布局有点类似于网格布局中自动放置网格项目(Auto-Placement)的布局,但又没有严格遵循该布局模式。

最著名的瀑布流布当属 Pinterest,比如他的搜索结果页面的布局效果:

有时候你会听到有人把这种布局称为“Pinterest布局”。

背后的故事

CSS网格布局其实已经很多年了,只不过受限于浏览器支持的限制,目前使用率并不算太高。至目前为止,CSS网格布局规范已经有多个版本了,Level 1Level 2 以及定义瀑布流布局模式的 Level 3,而且Level 1 和 Level 2是TR阶段,Level 3是ED阶段。

CSS网格布局是CSS的一种布局模式,它具有强大的布局能力,可以很好的控制方框及其内容的大小和位置。在Web布局的众多方式之中,也只有CSS网格布局是二维布局:即在两个维度上都需要对齐内容的布局

尽管许多布局可以用CSS网格来实现,但是Web上的一些布局用CSS网格也是无法限制的,比如瀑布流布局。

@Rachel Andrew曾经也说过,网格布局和瀑布流布局的结构就不有所不同,对于网格而言,他有严格的行和列,但对于瀑布流布局的结构来说,他并没有严格的行和列:

通常我们已经定义了行,但是列的作用更像是一个Flexbox布局,或者多列布局。即使使用多列布局来实现瀑布流布局和真正的瀑布流布局之前也有着关键区别。在多列布局中,项目是按列显示的。通常在瀑布流布局中,你希望它们是按行显示。

@Rachel Andrew个人建议不要把瀑布流布局作为CSS网格规范的一部分。因为瀑布流布局是一个相对专业的布局模式,实际上瀑布流布局根本也不是一个网格,它看上去更类似于Flexbox布局。

我想也是基于这些个原因,W3C规范才将瀑布流布局当作一个独立的规范,就算是要把他和CSS网格规范关联起来,也只能说CSS瀑布流布局规范(CSS Grid Level 3)是CSS网格布局的一个附本。

浏览器兼容性

CSS Grid Layout Level 3模块目前还仅仅是属于W3C规范的ED阶段。正如@Jen所说,

他不是一尘不变的,该规范中定义的一切都有可能会变化。

所以说,接下来的内容很有可能会随着该规范后续的更新有所变动。另外,就目前为止,只有Firefox和Firefox Nightly浏览器支持该规范,而且需要开启相关的配置。在Firefox和Firefox Nightly浏览器的URL地址中输入about:config,并搜索layout.css.grid-template-masonry-value.enabled,将其值设置为true

你可以尝试着在修改完配置的Firefox或Firefox Nightly浏览器中打开@Rachel Andrew在Codepen上提供的瀑布流案例,可以看到像下图这样的效果:

接下来,我们来看如何实现瀑布流布局效果。

我们可以使用成熟的CSS布局方式实现瀑布流布局

其实在《纯CSS实现瀑布流布局》一文中,和大家一起探讨了一些实现瀑布流布局的CSS方案。这几种方案中最接近的方案就是使用CSS的多列布局。

我们使用JavaScript在<body>中动态插入51<div class="item">,并且设置了相应的背景图像:

for (let i = 0; i <= 50; i++) {
    const div = document.createElement("div");
    div.classList.add("item");
    div.style.backgroundImage = `url(https://picsum.photos/500/500?random=${i})`;
    document.body.appendChild(div);
}

.item设置一些基本样式:

.item {
    border-radius: 10px;
    background-size: cover;
    background-position: center;
    height: 10em;
    position: relative;
    display: grid;
    grid-template-rows: 1fr auto;
    margin-bottom: 10px;
    break-inside: avoid;
}

并且给一些.item设置不同的高度:

.item:nth-child(2n) {
    height: 14em;
}
.item:nth-child(3n) {
    height: 18em;
}
.item:nth-child(4n) {
    height: 22em;
}
.item:nth-child(5n) {
    height: 24em;
}
.item:nth-child(6n) {
    height: 30em;
}
.item:nth-child(7n) {
    height: 34em;
}

.item:nth-child(8n) {
    height: 40em;
}

body使用column-countcolumn-gap来设置列数和列与列之间的间距:

body {
    column-count: 4;
    column-gap: 10px;
}

效果如下:

剩余80%内容付费后可查看

如需转载,烦请注明出处:https://www.w3cplus.com/css/masonry-layout-with-css-grid.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部