我需要实现一个砖石布局。但是,由于一些原因,我不想使用JavaScript来完成它。

参数:

所有元素都具有相同的宽度 元素具有服务器端无法计算的高度(图像加上不同数量的文本) 如果有必要,我可以接受固定数量的列

在现代浏览器中有一个简单的解决方案,列计数属性。

这个解决方案的问题是元素是按列排序的:

虽然我需要元素在行中排序,至少大约:

我尝试过的一些方法都不起作用:

显示项目:inline-block:浪费垂直空间。 让物品漂浮:左:lol,不。

现在我可以更改服务器端渲染,并将项目数量除以列数重新排序,但这很复杂,容易出错(基于浏览器决定如何将项目列表划分为列),所以我希望尽可能避免这种情况。

是不是有什么flexbox魔法让这一切成为可能?


2021年更新

CSS Grid Layout Level 3包括一个砌体特征。

代码看起来像这样:

grid-template-rows: masonry
grid-template-columns: masonry

截至2021年3月,它仅在Firefox中可用(激活该标志后)。

https://drafts.csswg.org/css-grid-3/#masonry-layout https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Masonry_Layout

最后更新;以下是原始答案


Flexbox

一个动态的砖石布局是不可能与flexbox,至少不是在一个干净和有效的方式。

Flexbox是一个一维布局系统。这意味着它可以沿着水平或垂直的线对齐项目。伸缩项仅限于其行或列。

真正的网格系统是二维的,这意味着它可以沿着水平线和垂直线对齐项目。内容项可以同时跨行和跨列,而flex项不能做到这一点。

这就是为什么flexbox构建网格的能力有限。这也是W3C开发另一种CSS3技术——网格布局(Grid Layout)的原因。


行包装

在具有flex-flow:行换行的伸缩容器中,伸缩项必须换行到新行。

这意味着一个伸缩项不能在同一行中的另一个项下面换行。

注意上面div #3是如何在div #1下面换行的,创建了一个新行。它不能包装在div #2下面。

因此,当物品不是一行中最高的时,就会留下空白,造成难看的空隙。


列包装

如果切换到flex-flow:列换行,则更容易实现类似网格的布局。然而,列方向容器马上就有四个潜在的问题:

Flex项目垂直流动,而不是水平流动(就像您在本例中需要的那样)。 容器水平展开,而不是垂直展开(就像Pinterest的布局)。 它要求容器有一个固定的高度,这样物品就知道在哪里包装。 在撰写本文时,它在所有主流浏览器中都有一个缺陷,即容器不能扩展以容纳额外的列。

因此,列方向容器在这种情况下和许多其他情况下都不是一个选项。


未定义项目尺寸的CSS网格

如果可以预先确定内容项的各种高度,网格布局将是您问题的完美解决方案。所有其他需求都在Grid的能力范围内。

必须知道网格项目的宽度和高度,以便缩小与周围项目的差距。

因此,网格,这是最好的CSS必须提供建立一个水平流动的砌体布局,在这种情况下,不足。

事实上,在CSS技术能够自动消除这些差距之前,CSS通常都没有解决方案。类似这样的事情可能需要重新循环文档,所以我不确定它是否有用或有效。

你需要一个脚本。

JavaScript解决方案倾向于使用绝对定位,它从文档流中删除内容项,以便重新排列它们,没有间隙。这里有两个例子:

Desandro Masonry

圬工是一个JavaScript网格布局库。它 通过将元素放置在基于可用的最佳位置来工作 垂直空间,有点像泥瓦匠把石头装在墙上。 来源:http://masonry.desandro.com/

如何建立一个像Pinterest一样的网站

(Pinterest)确实是一个很酷的网站,但我觉得有趣的是这些针板的布局方式……所以本教程的目的是重新创建这个响应块效果自己… 来源:https://benholland.me/javascript/2012/02/20/how-to-build-a-site-that-works-like-pinterest.html


定义了项目维度的CSS网格

对于内容项的宽度和高度已知的布局,这里有一个纯CSS水平流动的砌体布局:

grid-container { display: grid; /* 1 */ grid-auto-rows: 50px; /* 2 */ grid-gap: 10px; /* 3 */ grid-template-columns: repeat(auto-fill, minmax(30%, 1fr)); /* 4 */ } [short] { grid-row: span 1; /* 5 */ background-color: green; } [tall] { grid-row: span 2; background-color: crimson; } [taller] { grid-row: span 3; background-color: blue; } [tallest] { grid-row: span 4; background-color: gray; } grid-item { display: flex; align-items: center; justify-content: center; font-size: 1.3em; font-weight: bold; color: white; } <grid-container> <grid-item short>01</grid-item> <grid-item short>02</grid-item> <grid-item tall>03</grid-item> <grid-item tall>04</grid-item> <grid-item short>05</grid-item> <grid-item taller>06</grid-item> <grid-item short>07</grid-item> <grid-item tallest>08</grid-item> <grid-item tall>09</grid-item> <grid-item short>10</grid-item> <grid-item tallest>etc.</grid-item> <grid-item tall></grid-item> <grid-item taller></grid-item> <grid-item short></grid-item> <grid-item short></grid-item> <grid-item short></grid-item> <grid-item short></grid-item> <grid-item tall></grid-item> <grid-item short></grid-item> <grid-item taller></grid-item> <grid-item short></grid-item> <grid-item tall></grid-item> <grid-item short></grid-item> <grid-item tall></grid-item> <grid-item short></grid-item> <grid-item short></grid-item> <grid-item tallest></grid-item> <grid-item taller></grid-item> <grid-item short></grid-item> <grid-item tallest></grid-item> <grid-item tall></grid-item> <grid-item short></grid-item> </grid-container>

jsFiddle演示


它是如何工作的

建立一个块级网格容器。(内联网格将是另一个选择) grid-auto-rows属性设置自动生成行的高度。在这个网格中,每一行都是50px高。 网格间隙属性是网格列间隙和网格行间隙的简称。该规则在网格项之间设置10px的间距。(它不适用于物品和容器之间的区域。) grid-template-columns属性设置显式定义的列的宽度。

repeat符号定义了重复列(或行)的模式。

自动填充函数告诉网格在不溢出容器的情况下排列尽可能多的列(或行)。(这可以创建类似flex布局的flex-wrap: wrap的行为。)

minmax()函数的作用是:为每列(或行)设置最小和最大大小范围。在上面的代码中,每个列的宽度最小为容器的30%,最大为可用的空闲空间。

fr单位表示网格容器中空闲空间的一部分。它可以与flexbox的flex-grow属性相媲美。

通过grid-row和span,我们告诉网格项它们应该跨多少行。


浏览器对CSS网格的支持

Chrome - 2017年3月8日全面支持(版本57) Firefox - 2017年3月6日全面支持(版本52) Safari——2017年3月26日全面支持(10.1版) Edge - 2017年10月16日全面支持(版本16) IE11 -不支持当前规范;支持过时版本

这里是完整的图片:http://caniuse.com/#search=grid


酷的网格覆盖功能在Firefox

在Firefox开发工具中,当您检查网格容器时,在CSS声明中有一个很小的网格图标。点击它会在页面上显示网格的轮廓。

更多详情请访问:https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts


这是最近发现的涉及flexbox的技术:https://tobiasahlin.com/blog/masonry-with-css/。

这篇文章对我来说是有意义的,但我没有尝试使用它,所以我不知道是否有任何警告,除了Michael的回答中提到的。

下面是本文中的一个示例,使用order属性并结合:n -child。

堆栈段

.container { display: flex; flex-flow: column wrap; align-content: space-between; /* Your container needs a fixed height, and it * needs to be taller than your tallest column. */ height: 960px; /* Optional */ background-color: #f7f7f7; border-radius: 3px; padding: 20px; width: 60%; margin: 40px auto; counter-reset: items; } .item { width: 24%; /* Optional */ position: relative; margin-bottom: 2%; border-radius: 3px; background-color: #a1cbfa; border: 1px solid #4290e2; box-shadow: 0 2px 2px rgba(0,90,250,0.05), 0 4px 4px rgba(0,90,250,0.05), 0 8px 8px rgba(0,90,250,0.05), 0 16px 16px rgba(0,90,250,0.05); color: #fff; padding: 15px; box-sizing: border-box; } /* Just to print out numbers */ div.item::before { counter-increment: items; content: counter(items); } /* Re-order items into 3 rows */ .item:nth-of-type(4n+1) { order: 1; } .item:nth-of-type(4n+2) { order: 2; } .item:nth-of-type(4n+3) { order: 3; } .item:nth-of-type(4n) { order: 4; } /* Force new columns */ .break { flex-basis: 100%; width: 0; border: 1px solid #ddd; margin: 0; content: ""; padding: 0; } body { font-family: sans-serif; } h3 { text-align: center; } <div class="container"> <div class="item" style="height: 140px"></div> <div class="item" style="height: 190px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 120px"></div> <div class="item" style="height: 160px"></div> <div class="item" style="height: 180px"></div> <div class="item" style="height: 140px"></div> <div class="item" style="height: 150px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 140px"></div> <div class="item" style="height: 190px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 120px"></div> <div class="item" style="height: 160px"></div> <div class="item" style="height: 180px"></div> <div class="item" style="height: 140px"></div> <div class="item" style="height: 150px"></div> <div class="item" style="height: 170px"></div> <div class="item" style="height: 170px"></div> <span class="item break"></span> <span class="item break"></span> <span class="item break"></span> </div>


最后一个css唯一的解决方案,轻松创建砖石布局,但我们需要耐心,因为现在没有支持它。

这个特性在CSS Grid Layout Module Level 3中被引入

本模块介绍了砌体布局作为CSS网格容器的附加布局模式。

Then

通过为网格容器的一个轴指定砌体值,网格容器支持砌体布局。这个轴称为砌体轴,另一个轴称为网格轴。

一个基本的例子是:

.container { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-template-rows: masonry; /* this will do the magic */ grid-gap: 10px; } img { width: 100%; } <div class="container"> <img src="https://picsum.photos/id/1/200/300"> <img src="https://picsum.photos/id/17/200/400"> <img src="https://picsum.photos/id/18/200/100"> <img src="https://picsum.photos/id/107/200/200"> <img src="https://picsum.photos/id/1069/200/600"> <img src="https://picsum.photos/id/12/200/200"> <img src="https://picsum.photos/id/130/200/100"> <img src="https://picsum.photos/id/203/200/100"> <img src="https://picsum.photos/id/109/200/200"> <img src="https://picsum.photos/id/11/200/100"> </div>

如果您启用此处解释的特性,这将在Firefox上产生以下结果:https://caniuse.com/?search=masonry

打开火狐浏览器,在url栏写上:config 用砖石做搜索 你会得到一面旗帜,让它成真

如果我们减少屏幕屏幕,反应部分是完美的!


我发现这个解决方案,它很可能与所有浏览器兼容。

注意:如果有人发现任何错误或浏览器支持问题。请更新这个答案或评论

CSS prof佩里支持参考:

列计数,间隙,填充,分页

注意:page-break-inside该属性已被break-inside属性所取代。

.container { -moz-column-count: 1; column-count: 1; -moz-column-gap: 20px; column-gap: 20px; -moz-column-fill: balance; column-fill: balance; margin: 20px auto 0; padding: 2rem; } .container .item { display: inline-block; margin: 0 0 20px; page-break-inside: avoid; -moz-column-break-inside: avoid; break-inside: avoid; width: 100%; } .container .item img { width: 100%; height: auto; } @media (min-width: 600px) { .container { -moz-column-count: 2; column-count: 2; } } @media (min-width: 900px) { .container { -moz-column-count: 3; column-count: 3; } } @media (min-width: 1200px) { .container { -moz-column-count: 4; column-count: 4; } } CSS-Only Masonry Layout <div class="container"> <div class="item"><img src="https://placeimg.com/600/400/animals" alt=""></div> <div class="item"><img src="https://placeimg.com/600/600/arch" alt=""></div> <div class="item"><img src="https://placeimg.com/600/300/nature" alt=""></div> <div class="item"><img src="https://placeimg.com/600/450/people" alt=""></div> <div class="item"><img src="https://placeimg.com/600/350/tech" alt=""></div> <div class="item"><img src="https://placeimg.com/600/800/animals/grayscale" alt=""></div> <div class="item"><img src="https://placeimg.com/600/650/arch/sepia" alt=""></div> <div class="item"><img src="https://placeimg.com/600/300/nature/grayscale" alt=""></div> <div class="item"><img src="https://placeimg.com/600/400/people/sepia" alt=""></div> <div class="item"><img src="https://placeimg.com/600/600/tech/grayscale" alt=""></div> <div class="item"><img src="https://placeimg.com/600/200/animals/sepia" alt=""></div> <div class="item"><img src="https://placeimg.com/600/700/arch/grayscale" alt=""></div> </div>