使用JS或CSS如何实现瀑布流布局,几种方案介绍


本文摘自PHP中文网,作者青灯夜游,侵删。

本篇文章带大家了解一下瀑布流布局,介绍一下三种靠谱JS方案,以及N种不靠谱CSS方案。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

本着实用精神,我们今天来分享一下瀑布流布局昨天有个小兄弟问我怎么做,我找了半天没找到,啊原来写在内网了)。

演示地址: http://www.lilnong.top/static/html/waterfall.html

瀑布流布局是什么?

比如说 花瓣网蘑菇街 (我下面贴图了), 这些网站在显示内容的时候就使用了瀑布流布局。

我们也想做一个展示我们设计稿(定宽,不定高)的页面,瀑布流是很棒的一种方案。

瀑布流布局其核心是基于一个网格的布局,而且每行包含的项目列表高度是随机的(随着自己内容动态变化高度),同时每个项目列表呈堆栈形式排列,最为关键的是,堆栈之间彼此之间没有多余的间距差存大。还是上图来看看我们说的瀑布流布局是什么样子。

网站蘑菇街花瓣网京东VV
截图1.png2.png3.png4.png
方案分通道absolute

grid、inline、float 魔性方案

也算是纯 CSS 方案吧,本质上来讲是依赖文档流,从左到右,从上到下。

方案gridinlinefloatbootstrap-grid
截图5.png6.png7.png8.png

可以看到在文档流布局中有非常明显的的概念,当一个行被撑开就会留下空白,行与行不会重叠。这里最魔性的就是 float 布局了。

DOM 结构

1

2

3

div.list     // 设置 gird 或者 block,注意清除浮动

  div.item   // 设置为 inline 或者 float,使其能流动

    img      // 设置定宽,高度自适应,间距等。

grid 方案说明

1

2

3

4

5

6

7

8

.wrap-waterfall--grid img{vertical-align: top;width: 100px}

.wrap-waterfall--grid .list{

    display: grid;

    grid-gap: 10px;

    /* 可以看到,网格大小,占据位置是需要提前设定的 */

    grid-template-columns: repeat(4, 1fr);

    grid-auto-rows: minmax(50px, auto);

}

grid 在某些情况下会比 flex 好用。比如说需要突破行的限制,但是只适用于固定布局,如下图的布局,如果不使用grid你会如何实现呢?

9.png

网传有 gird 实现瀑布流布局的方案,但是我看了几个他们不是色块,就是图片变形、裁剪,方案是用 nth-child 定高,太恐怖了吧

columns、flex CSS实现 不靠谱方案

也是纯 CSS 方案,相比较上面的方案而言,方案已经可以接受,只是还有部分问题。

  • 顺序是先垂直,后水平
  • (columns)兼容性问题
  • (flex)需要给一个固定高度,会出现超出设定列,以及无法充满设定列。
方案columnsflex
截图10.png11.png

columns 方案

天生支持,只需要给父级设置即可 columns: 4; column-gap: 6px;

flex 方案

flex-flow: column wrap;height: 2300px; 默认情况下是水平排列,通过修改为垂直排列并且允许换行,之后把通过固定高度使内容换行。

absolute、通道 高度计算方案 靠谱方案

方案absolute取余分通道计算高度分通道
头部截图12.png13.png14.png

这里的方案就靠谱起来了,可以满足我们使用要求。

我们来回忆一下我们的需求:展示一些内容,内容有特性定宽,不定高。不定高一般是因为内容长度或者高度不一致导致的,常见内容又分为两种文字和图片

  • 文字的话,在没有异步字体的情况下,可以理解为同步就可以获取到盒子高度。

  • 图片的话,因为加载是异步的,所以获取盒子的真实高度也是异步的。但是这里一般分为两种情况

  • 无高度,那么可以通过onload来监听图片加载完成。等图片加载完成再去获取高度。

  • 有高度,这种方案一般用在封面图、或者文章中,在上传图片的时候会保存原图尺寸,这个时候我们就可以直接使用已有数据。

获取图片高度

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// 用于获取图片的真实高度

naturalHeight: 1180

// 用于获取图片的真实宽度

naturalWidth: 1200

 

//用户获取图片当前的渲染高度(会受 css 影响)

height: 98

//用户获取图片当前的渲染宽度(会受 css 影响)

width: 100

 

// 可返回浏览器是否已完成对图像的加载。如果加载完成,则返回 true,否则返回 fasle。

complete 属性

// 可以监听到图片加载完成的动作

onload

基于上面的内容,那我们可以先判断 complete 属性,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

function getImageSize(img){

    if(img.complete){

        return Promise.resolve({

            naturalHeight: img.naturalHeight,

            naturalWidth: img.naturalWidth,

            height: img.height,

            width: img.width,

        })

    }else{

        return new Promise((resolve, reject)=>{

            img.addEventListener('load', ()=>{

                resolve({

                    naturalHeight: img.naturalHeight,

                    naturalWidth: img.naturalWidth,

                    height: img.height,

                    width: img.width,

                })

            })

        })

    }

}

/*

// 测试用例

el = document.createElement('img');

el.src = 'http://cors-www.lilnong.top/favicon.ico?'+Math.random()

 

getImageSize(el).then(console.log).catch(console.error)

setTimeout(()=>getImageSize(el).then(console.log).catch(console.error), 1000)

*/

absolute 计算高度方案

因为普通的布局已经无法满足我们的需求,所以我们可以考虑通过 position: absolute 来使内容通过绝对定位来显示

阅读剩余部分

相关阅读 >>

javascript怎么隐藏元素值

css怎么把东西往右移

css六边形怎么画

javascript中random用法是什么

javascript怎么替换所有字符串

css如何设置背景图片的大小

css中display属性怎么用

css放在哪里

怎么用css实现左右运动效果

javascript截取字符串的方法有哪些

更多相关阅读请进入《javascript》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...