瀑布流布局

瀑布流布局是一种新型的布局方式,可以将大小不一的图片完整的显示在页面上,并且在杂乱的布局中保持着一定的美感,今天学习了一下如何使用瀑布流布局,总结了有以下三种方式。(瀑布流还可以使用grid布局实现,还没有学习过这种方式)
瀑布流的示例
瀑布流的实现方法可以用纯CSS,也可以用JS实现,如何选取决于需求,这几种方法各有优略,如何选取取决于需求。以下案例均采用如下的html代码

<div class="container" id="con">
        <div class="item">
                <img src="../img/1.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/2.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/3.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/4.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/5.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/6.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/7.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/8.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/9.jpeg" alt="">
        </div>
        <div class="item">
            <img src="../img/10.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/11.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/12.jpeg" alt="">
        </div>
        <div class="item">
            <img src="../img/13.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/14.jpeg" alt="">
        </div>
        <div class="item">
                <img src="../img/15.jpeg" alt="">
        </div>
    </div>

1.CSS布局

使用column-count属性

实现代码:

 .container{
            column-count: 4;//想要排成的列数
            column-gap: 0;
        }
        .item img{
            width: 100%;
        }

实现效果:
在这里插入图片描述
使用column-count属性将一个盒子分为多列展示数据 ,使用column-gap:0px将列间间距设置未0,方便我们自定义间距。

  • 优点
  1. 简单,只需给父盒子两行代码
  2. 列数不会随着浏览器的宽度而改变,例如:指定列数为4就只能显示4列
  • 缺点:如下图,我们可以看到,图片的位置是按照从上往下排序,如果我们需要一些动态加载图片的业务,那么新加入的图片将不会加入页面的最低端,不符合我们的业务需求

在这里插入图片描述

使用flex布局

实现代码:

 .container{
            display: flex;
            flex-direction: column;
            flex-wrap: wrap;
            /* 需要指定高度 */
            height: 800px;
        }
        .item{
            width: 25%;
        }

        .item img{
            width: 100%;
        }

实现效果:
在这里插入图片描述
使用弹性盒子,给弹性元素指定列排列,然后给每个元素指定宽度(宽度设置为(1/列数)如果想要排成4列就设置成25%,如果想要排成5列就设置成25%以此类推)。
由于设置为列排列,当元素的累计高度没有超过指定的高度时,首先会在第一个列上堆叠元素
在这里插入图片描述
由于我们设置了flex-wrap:wrap导致如果超出了设置的高度,元素将会换行,由于我们设置的排列方向是按列排列,因此超出的元素将会展示在第二列
在这里插入图片描述
以此类推,只要我们元素的数量合适,能够在指定的高度下填满4列,就能完成瀑布流了布局了,可以看见此时还是图片按照列的顺序排列的,仍然无法做到新的图片展示在下方的业务。

优化

	.container{
            display: flex;
            flex-direction: column;
            flex-wrap: wrap;
            /* 需要指定高度 */
            height: 1600px
        }
        /**新加入的代码*/
        .item:nth-child(4n+1){
            order: 1;
        }
        .item:nth-child(4n+2){
            order:2;
        }
        .item:nth-child(4n+3){
            order: 3;
        }
        .item:nth-child(4n){
            order: 4;
        }
        /**新加入的代码*/
        .item{
            width: 25%;
            position: relative;
            counter-increment: item-counter;
        }

        .item img{
            width: 100%;
        }
        .item::after{
            position:absolute;
            background-color: red;
            color: white;
            left: 0;
            top: 0;
            content: counter(item-counter);
        }

期望得到这样的效果:
在这里插入图片描述
实际的效果却是:
在这里插入图片描述
几经查证发现,由于图片大小差距过大,导致每一行显示图片的数量不一样,导致order失效
但当每一列图片数量相等的时候,可以达成想要的效果

总结:

  • 优点:
  1. 同样相对简单
  2. 如果每列数量差图片数量相同,则可以实现新的图片显示在最下方的业务
  • 缺点:
  1. 列数不会随着浏览器的宽度而改变
  2. 需要指定高度,并且在每一列放置合适数量的图片。
  3. 如果没有给容器设置固定宽度,则当容器宽度缩小时,图片的宽度相应的缩小,由于图片的高度是auto,即按图片原比例展示,因此图片高度会相应减少,由于高度指定,图片数量固定,则可能会出现图片占不满列数的情况,,具体问题如下图

在这里插入图片描述

JS 方法实现

原理:通过JS,根据每个图片的宽度计算出需要放置多少行,将所有图片设置绝对定位,逐一计算出该图片所在的top和left进行定位
实现代码:

		.container{
            position: relative;
        }
        .item{
            width: 200px;
            height: auto;
            position: absolute;
        }

        .item img{
            width: 100%;
        }

//当页面加载的时候调用
window.onload = function(){
	//页面初始化调用
    waterFall()
    //每次页面改变大小调用
    window.onresize = waterFall
}
function waterFall(){
   // 1. 设置container盒子的宽度
   //      注意:浏览器的可视区域的宽度 / 一个item元素的宽度 = 一行的排列的元素的个数
   let container = document.getElementById("con")
   let item = document.getElementsByClassName("item")
   //获取元素的宽度(含border,padding)
   let width = item[0].offsetWidth 
   //计算出浏览器窗口的宽度
   let clientWidth = document.documentElement.clientWidth;
   //计算出应该放几列(向下取整)
   let columnCount = Math.floor(clientWidth / width)
   //设置容器(父盒子)的宽度
   container.style.width = columnCount*width+"px"

   // 2.设置每一个item元素的排列位置
   //  第一行整体的top值都是0 后面的依次找上一行高度最小的容器,在它下面进行排列
   let hrr = []
   for(let i= 0 ;i<item.length;i++){
   		//定位第一行的图片
       if(i<columnCount){
           item[i].style.top = "0px"
           item[i].style.left = i* width+"px" 
           hrr.push(item[i].offsetHeight)
       }else{
           //第一行之后的
           //选择总高度最小的列
           let min = Math.min(...hrr)
           let index = hrr.indexOf(min)
           //将每个元素定位到当前总高度最小的列下
           item[i].style.top = min+"px"
           item[i].style.left = index * width+"px" 
           //当前定位的元素加入该列
           hrr[index] += item[i].offsetHeight
       }
   }

为什么每次都要将图片放置在高度最小的列上呢?
因为图片高度不一的情况,如果按下标顺序一个一个排列,最终虽然每一列上图片的数量是一样的,但是显示的高度可能相差甚远,因此选择将每个图片放在高度最小的列上让每一列的总高度不会相差太大。

实现效果:
在这里插入图片描述
当浏览器宽度缩小时,图片列数自动匹配。
![在这里插入图片描述](https://img-blog.csdnimg.cn/1bb8829124d241ae81e8e9d645471954.png

  • 优点:
  1. 列数随浏览器窗口大小动态改变
  2. 可以实现新图片在最下方展示
  • 缺点:
  1. 代码较为复杂
  2. 由于使用js,会消耗一些浏览器性能,当图片多了的时候可能导致卡顿。

总结:
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐