文章很长,因为介绍了如何一步一步进化到最后接近完美的效果的,不想读的同学可以直接跳到最后一个大标题之后看代码、demo 及原理就好,或者也可以直接看下面这个链接的源代码.不过还是建议顺序读下去,因为后面的原理需要前面的内容做为铺垫,主要是在处理边角问题上.
先看下效果,要不然各位可能没动力读下去了,实在是有点长,可以试着 resize 或者 zoom 一下看看动态效果: Cats
PS:文中的一些 demo 为了方便展示源代码用了 jsbin,但 jsbin 偶尔抽风会显示不出效果,试着在源代码编辑框里不改变代码意思的情况下编辑一下(比如在最后打一下回车)应该就可以了,或者查看一下你浏览器的翻墙设置,因为里面引入了 Google CDN 上的文件,有可能是因为 js 加载不成功导致的.
PS2:Demo 中用到的所有图片都来自 http://500px.com 网站,图片版权归原作者所有.图片地址末尾的数字即为其在 http://500px.com 上的 id,如果你喜欢某张图片,可以通过 https://500px.com/photo/[id]/ 这个地址访问到图片原始页面.
好了,正文开始.
开始之前,先对比一下三种比较常见的图片布局的差异
花瓣:
此种布局为比较常见的等宽布局,所有图片的宽度是一样的
由于图片是等比拉伸(等比拉伸的意思是图片的宽和高变化相同的比例,也就是图片展示的宽高比与原始宽高比一致),而每张图片的宽度又是一样的,所以图片的高度就必然不一样了
这种布局的缺点是,由于每张图片展示的高度的不一致,图片不是按一般的阅读顺序展示的,因为可能连续的多张图片顶部的高度不一样,而人眼又习惯于水平扫描,所以用户就有可能漏看某些照片
图片瀑布的底部一般是对不齐的
虽然底部很难完全对齐,但使用 JS 对图片顺序进行重排能够让底部尽量对齐,所以此种布局在 reflow 的时候(比如resize,zoom)必然要有 JS 的参与
Google Photos,500px,图虫等,以 Google Photos 为代表的即不等宽也不等高的图片布局有如下特点:
图片也没有被非等比拉伸
每行的图片在水平方向上也占满了屏幕,没有多余的空白
因为以上两个条件,所以每行的图片高度必然会不一样,否则无法做到图片在水平方向上占满屏幕
图片是按顺序展示的,比较符合人眼阅读顺序,Google Photos 因为照片有拍摄时间这个属性,必须满足这个条件
底部是对齐的
Google Photos 的布局中,当某几个日期的照片太少时,多个日期的照片会合并展示在同一行,当然这不是本文讨论的重点
Instagram
正方形图片布局,就不多说了——
以上介绍的前两种布局都有一个共同点,那就是图片没有经过非等比拉伸,也就是说图片里的内容没有变形,也没有被裁剪,只是放大或者缩小,这是目前图片类应用在展示图片上的一个趋势,应该说,很少有专做图片的网站会把照片非等比拉伸显示(变形拉伸真的给人一种杀马特的感觉…),最次的展示方式也就是把图片裁剪成正方形后展示在一个正方形的区域里,类似于正方形容器的 background-size: cover; 的效果.
另外,在花瓣的布局中,比较宽的图片展示区域会比较小;而在第二种布局中,则是比较高的图片展示区域会比较小.
但是,在第一种布局中,因为宽度是定死了的,所以高宽比小到一定程度的图片,显示区域会非常小.而在第二种布局中,因为不同行的高度是不一样的,如果比较高的图片出现在比较高的行,还是有可能展示的稍大些的.
总体来说,以 Google Photos 为代表的图片布局,在显示效果上更优.关于如何使用 JS 来完成 Google Photos / 500px 布局的算法,这里就不讨论了,读者可以自己思考一下——
思考完成后可以看看这个页面对这个布局的动态演示,打开页面,等图片全部加载完成后点击页面顶部的 layout 按钮.
Demo 演示了如下的布局方式:先按照相同的高度把图片排列起来,然后按行对每行的图片进行等比放大,放大到当前行的所有图片正好跟容器两边对齐,布局完成.
OK,下面根据上面的分析稍微总结一下评判图片布局优劣的一些标准:
是否能尽量按原始列表中的顺序输出
能否按人眼的扫描顺序输出,即行高相同
图片能否按照原始比例展示,或者尽量按原始比例展示
每张图片的展示面积能否尽量接近,实际上在想完全展示照片的布局中,这一条是很难达成的
图片不被非等比拉伸,内容不变形,内容展示完全
第一次看到类似 Google Photos 照片列表的布局已经不记得是在哪里了,当时只是觉得这种布局肯定需要 JS 参与,因为每行图片高度相同的情况下不可能那么恰到好处的在容器两端对齐,且所有图片之间的间距大小也一样(如果间距大小不一样但两端对齐,可以使用 inline 的图片加上 text-justify 来实现,在图片较小的时候(比如搜索引擎的图片结果)也不失为一种选择).然而通过观察,发现每行的高度并不相同,就确认了必然需要 JS 参与才能完成那样的布局.
然而当越来越多的开始网站使用这样的布局时,做为一个热衷于能用 CSS 实现就不用 JS 的前端工程师,我就在考虑,能否仅用 CSS 实现这样的布局呢?尤其是不要在 resize 时重新计算布局.
在经过一些尝试后,我发现可在一定程度上用纯 CSS 实现类似的布局.这里说的一定程度上仅使用 CSS 实现布局,我的意思是:布局一但渲染完成,布局后序的 resize,zoom 都可以在没有 JS 参与的情况下保持稳定,也就是说,首次的渲染甚至可以通过服务器完成,整个过程可以没有 JS 参与,所以说成是用纯 CSS 实现也不过分.
如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h63640.shtml