我需要实施砌体布局。但是,出于多种原因,我不想使用 JavaScript 来完成它。
参数:
- 所有元素具有相同的宽度
- 元素具有服务器端无法计算的高度(图像加上不同数量的文本)
- 如果必须的话,我可以接受固定数量的列
有一个适用于现代浏览器的简单解决方案, 即 column-count
属性。
该解决方案的问题在于元素按列排序:
虽然我需要按行对元素进行排序,但至少大致如下:
我尝试过但无效的方法:
现在我 可以 更改服务器端渲染并重新排序项目,将项目数除以列数,但这很复杂,容易出错(基于浏览器决定将项目列表拆分为列的方式),所以我想尽可能避免它。
是否有一些 flexbox 魔法使这成为可能?
原文由 Pekka 发布,翻译遵循 CC BY-SA 4.0 许可协议
2021 更新
CSS 网格布局级别 3 包括一个
masonry
特性。代码将如下所示:
截至 2021 年 3 月,它仅在 Firefox 中可用(激活标志后)。
结束更新;原回答如下
弹性盒
Flexbox 不可能实现动态砌体布局,至少不能以干净高效的方式实现。
Flexbox 是一个一维布局系统。这意味着它可以沿水平或垂直线对齐项目。弹性项目仅限于其行或列。
真正的网格系统是二维的,这意味着它可以沿水平和垂直线对齐项目。内容项目可以同时跨越行和列,这是弹性项目无法做到的。
这就是为什么 flexbox 构建网格的能力有限。这也是 W3C 开发了另一种 CSS3 技术 Grid Layout 的原因。
row wrap
在带有
flex-flow: row wrap
的弹性容器中,弹性项目必须换行到新 _行_。这意味着 _弹性项目不能换行在同一行中的另一个项目之下_。
请注意上面的 div #3 如何包裹在 div #1 之下,创建一个新行。它不能包裹在 div #2 之下。
结果,当项目不是行中最高的时候,空白仍然存在,造成难看的间隙。
column wrap
如果切换到
flex-flow: column wrap
,则更容易实现类似网格的布局。然而,列向容器有四个潜在的问题:因此,列方向容器在这种情况下不是一个选项,在许多其他情况下也是如此。
项目尺寸未定义的 CSS 网格
如果可以预先确定内容项的各种高度, 网格布局将是您问题的完美解决方案。所有其他要求都在 Grid 的能力范围内。
必须知道网格项目的宽度和高度,以便缩小与周围项目的差距。
因此,Grid 是构建水平流动的砖石布局的最佳 CSS,但在这种情况下达不到要求。
事实上,在能够自动缩小差距的 CSS 技术出现之前,CSS 通常没有解决方案。像这样的事情可能需要重排文档,所以我不确定它会有多大用处或效率。
你需要一个脚本。
JavaScript 解决方案倾向于使用绝对定位,它从文档流中删除内容项,以便重新排列它们而没有间隙。这里有两个例子:
定义了项目尺寸的 CSS 网格
对于内容项的宽度和高度已知的布局,这里是纯 CSS 中的水平流动砌体布局:
jsFiddle 演示
怎么运行的
inline-grid
是另一个选项)grid-auto-rows
属性设置自动生成的行的高度。在这个网格中,每一行都是 50px 高。grid-gap
属性是grid-column-gap
和grid-row-gap
的简写。此规则在网格项 之间 设置 10px 的间距。 (它不适用于项目和容器之间的区域。)grid-template-columns
属性设置明确定义的列的宽度。repeat
表示法定义了重复列(或行)的模式。auto-fill
函数告诉网格在不溢出容器的情况下排列尽可能多的列(或行)。 (这可以创建与 flex 布局的flex-wrap: wrap
类似的行为。)minmax()
函数设置每列(或行)的最小和最大大小范围。在上面的代码中,每列的宽度最小为容器的 30%,最大为可用空间的宽度。fr
单元 表示网格容器中可用空间的一部分。它相当于 flexbox 的flex-grow
属性。grid-row
和span
我们告诉网格项它们应该跨越多少行。CSS 网格的浏览器支持
这是完整的图片: http ://caniuse.com/#search=grid
Firefox 中的炫酷网格覆盖功能
在 Firefox 开发工具中,当您检查网格容器时,CSS 声明中有一个微小的网格图标。单击它会在页面上显示网格的轮廓。
此处有更多详细信息: https ://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts