让我们来看一下一种超轻量级的方法,用于为一组任意大小的照片创建水平砌体效果。将任何一组照片放入其中,它们将无缝地排列在一起,没有任何间隙。
该解决方案不仅轻量级,而且非常简单。我们将使用一个无序图像列表和仅 17 行 CSS 代码,其中flexbox
和 object-fit
是主要的实现者。
为什么?
我有两个爱好:用照片记录我的生活,以及想出有趣的方法来组合 CSS 属性,包括旧的和新的。
几周前,我参加了XOXO 并拍摄了大量照片,最终缩减到了一套不错的 39 张照片。由于想要拥有我的内容,在过去的几年里,我一直考虑建立一个简单的照片博客,但从未能够实现我心目中的布局:一个简单的砌体布局,照片在尊重其纵横比的同时填充行(想想 iOS 上的 Photos.app、Google Photos、Flickr……)。

我做了一些研究,看看是否有任何轻量级、无 JavaScript 的选项,但找不到任何适合我需求的选项。在遇到一些航班延误后,我开始尝试一些代码,限制自己尽可能地保持简单(因为这是我乐趣的定义)。
基本标记
由于我基本上是在创建一个图像列表,所以我选择了无序列表
<ul>
<li>
<img>
</li>
<!-- ... -->
<li>
<img>
</li>
</ul>
向 Flexbox 致敬
然后出现了一连串的灵光乍现时刻
- Flexbox 非常适合通过根据单元格内容确定单元格宽度来填充行。
- 这意味着所有图片(横向或纵向)都需要具有相同的高度。
- 我可以使用
object-fit: cover;
来确保图片填充单元格。
理论上,这听起来像是一个可靠的计划,并且让我得到了一个我大约 90% 满意结果。
ul {
display: flex;
flex-wrap: wrap;
}
li {
height: 40vh;
flex-grow: 1;
}
img {
max-height: 100%;
min-width: 100%;
object-fit: cover;
vertical-align: bottom;
}
注意:40vh
似乎是桌面浏览器最佳的初始方法,它以合理的大小显示两行完整的图片,并暗示下方还有更多。这也允许每行显示更多图片,从而显著改善纵横比。
最后一行拉伸
我遇到的唯一问题是 Flexbox 非常希望填充所有行,并且它对最后一行图片的纵横比做了一些愚蠢的事情。这可能是我对这个布局最不喜欢的一点,但我不得不将一个空的<li>
元素添加到列表的末尾。
<ul>
<li>
<img>
</li>
<!-- ... -->
<li>
<img>
</li>
<li></li>
</ul>
结合这段 CSS 代码
li:last-child {
flex-grow: 10;
}
注意:此处使用“10”没有科学依据。在我的所有测试中,这提供了最佳结果。
演示
查看 CodePen 上 Tim Van Damme (@maxvoltar) 编写的作品
自适应照片布局
在 CodePen 上。
视口优化
在处理不同的视口方向时,需要牢记一些注意事项。
纵向
如果您的视口高度大于宽度,则此方法会限制每行的图片数量,从而弄乱其纵横比。要解决此问题,您可以使用此简单的媒体查询使图片行变矮
@media (max-aspect-ratio: 1/1) {
li {
height: 30vh;
}
}
短屏幕
为了帮助横向的小型设备,增加图片的高度有助于尽可能地看到它们
@media (max-height: 480px) {
li {
height: 80vh;
}
}
较小的屏幕 + 纵向
大多数手机的宽度不足以允许 Flexbox 正确执行其工作,而不会使图片缩小,因此在这里我选择不尝试每行显示多张图片。但是,仍然值得在此处设置最大高度,这样您至少可以了解列表中下一张图片的提示。
@media (max-aspect-ratio: 1/1) and (max-width: 480px) {
ul {
flex-direction: row;
}
li {
height: auto;
width: 100%;
}
img {
width: 100%;
max-height: 75vh;
min-width: 0;
}
}
就是这样!
这种方法没有完全尊重图片的纵横比(但很接近),并且偶尔会导致一些奇怪的结果,但我绝对喜欢它的简洁性和灵活性。想要让您的画廊水平滚动而不是垂直滚动?只需进行一些调整即可实现。画廊中有 1000 张图片还是只有一张?它们看起来都会很好。对纵横比不确定?Flexbox 是您的最佳选择。如果您还没有,请再次查看演示,并告诉我您的想法!
额外内容
根据这些照片的大小,这样的页面可能会很快增长到几兆字节。在我的博客中,我添加了loading="lazy"
来解决这个问题。在图片上设置了该属性后,它只会在您滚动时接近它们时加载。目前仅在 Chrome 中受支持,但您可以自己实现更受支持的技术。
干得好!使用内边距修改版本非常容易,可以获得不同的感觉
非常好,在看到这条评论之前,我正在考虑自己尝试一下。
非常酷。您可以通过将
flex-grow:10
移动到ul:after
伪元素来摆脱您不喜欢的最后一个li
查看 CodePen 上 Will Anderson (@andwilr) 编写的作品
自适应照片布局
在 CodePen 上。
无需在末尾使用那个空的
<li></li>
。您可以将伪元素附加到<ul>
,它将充当最后一个 Flex 项目ul::after {
内容:"";
flex-grow: 10;
}
太棒了,我正好想实现这种布局!我发现,为最后一个项目添加一个 flex-basis(我认为可以用
::after
替换)可以帮助最后一个图像填满最后一行。嗨,
这是一种创建简洁照片网格的非常有趣的方法。
不过有一点:与其在末尾添加一个空的 li,不如在网格上使用 after 元素,高度为零,flex-grow: 10。
如果元素被单独推到一行,同时保持将元素推到左侧的效果,则 height: 0 不会有任何影响。
这应该可以在不添加额外的空元素的情况下完成工作。
你们太棒了!使用
::after
完全被我忽略了。感谢分享!
我一直在使用你的代码(以及我的一些图片),我注意到有时有些图片的高度没有正确覆盖,因此你可以在图片下方看到背景。你知道如何解决这种行为吗?
我还没有遇到过这个问题!你使用的是哪个浏览器?
有没有办法让它在 Bootstrap 4 中工作?那里的布局似乎不起作用,我猜是因为<ul> 和 <li> 的默认样式。
我从未使用过 Bootstrap(总是自己编写系统)
你好 - 布局很酷...问题是,如果你要将其整合到 WordPress 子主题中,你是否有任何关于要修改哪些文件或配置哪些模板以实现类似照片布局的建议?..
我唯一用过的 CMS 是 Textpattern。而且那是...很久以前的事了。
太棒了。这启发我去看看它在我的实际网站上的表现如何。像其他人一样,我在看到评论之前添加了 gutter、box-shadow 和 border。我希望我的链接和悬停功能,并能在我的 75% 的主要内容部分(使用 Bootstrap 4)中工作。我借鉴了 ul:after 和 border-radius 的建议。结果:[ https://codepen.io/Gene/pen/LYYVPVm ]
这种 :cover 方法有一些轻微的缺点,具体取决于你的品味 - 它会缩放裁剪所有内容(修复和 :cover 减少的技巧?),并且纵向照片通常只有横向照片的一半大小。由于这些原因,我最终决定只是用我学到的知识来改进我自己的基于网格的长宽比画廊。
我仍然喜欢这个想法和这些最小代码示例。它只需要创造力才能将其应用到包含库和样式包的网站中间。我会保留一份副本,以便在更合适的地方使用!夹心式赞美!
这是目标
很酷很干净。我把它封装成一个 React 函数 https://codepen.io/mjunaidi/pen/JjjJWoo
你好
不错的布局。
如何从文件夹中导入所有图像,并使用此布局在网站上显示它们?
因此,当我在文件夹中添加或删除图像时 -> 图像也会在网站中添加/删除。
感谢这个鼓舞人心的示例。我用它创建了一个我的 Flickr 帐户最近上传内容的墙,网址是 https://www.rockland.dk/show/?post=412 。没什么特别的。几乎是复制粘贴你的代码,除了它是一个固定宽度的博客,所以跳过了视口优化。只是想说声谢谢分享这个示例(也许我应该看看关于对额外的尾随 li 元素使用 :after 的建议)…
查看此图像,以及你在 flex 示例中的相同图像
https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05586_oj8jfo.jpg
你会看到它在垂直方向上被切掉了。这是预期的吗?
嗨!是的,这是预期的,因为演示在 img 元素上使用了
object-fit: cover;
。这将使内联图像的行为类似于 CSS 背景图像,并在其容器停止的地方裁剪。补充一下我的上一条评论,这件事在恰好是本页顶部的示例中很明显!
谢谢这个。
但是,如何在每个图像下方添加描述,谢谢