前端实现瀑布流布局的方法汇总

·  阅读 2538

方法总结:

方法一:纯CSS布局

缺点: 每个item是从上到下排列的。如果需要动态加载item,(⊙o⊙)…那真是糟糕透顶! 这个就了解了解,实际项目中不会这样写的。

在这里插入图片描述

方法二:JS计算位置

利用绝对定位absolute,通过JS计算每个item的的topleft

实际项目中图片的宽高一般是由后端返回过来。这样前端就不需要计算图片宽高,用户体验会更好! 总之,具体问题具体分析,万一后端没返回宽高的勒 (︶︹︺)

在这里插入图片描述

方法三:使用插件

持续更新中。。。

方法1.1:multi-column多列布局瀑布流

演示代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>multi-columns瀑布流布局</title>
    <style>
        .container {
            margin: 0 auto;
            width: 1000px;
            column-count: 5; /* 列数 */
            column-gap: 20px; /* 列间距 */
        }
        .item {
            margin-bottom: 10px;
            /* 防止多列布局,分页媒体和多区域上下文中的意外中断 */
            break-inside: avoid;
        }
        .item img{
            width: 100%;
            height:100%;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item">
            <img  src="img/bg1.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg2.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg3.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg4.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg5.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg6.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg7.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg8.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg9.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg10.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg11.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg12.jpg" alt="" />
        </div>
    </div>
</body>

</html>

复制代码

方法1.2:Flex弹性布局瀑布流

演示代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Flexbox瀑布流布局</title>
    <style>
        .wrapper{
            display: flex;
            flex-direction: row; /* 每列container 水平排列*/
            justify-content: space-between; /* 两端对齐,间隔相等*/
            margin: 0 auto;   /* 整体居中 */
            width:1000px;
        }
        .container{
            width:240px;
        }
        .item{
            margin-bottom:10px;
        }
        .item img{
            width:100%;
        }

    </style>
</head>
<body>
    <div class="wrapper">
        <div class="container">
            <div class="item">
                <img  src="img/bg1.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg2.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg3.jpg" alt="" />
            </div>
        </div>
        <div class="container">
            <div class="item">
                <img  src="img/bg4.jpeg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg5.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg6.jpg" alt="" />
            </div>
        </div>
        <div class="container">
            <div class="item">
                <img  src="img/bg7.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg8.jpeg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg9.jpg" alt="" />
            </div>
        </div>
        <div class="container">
            <div class="item">
                <img  src="img/bg10.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg11.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg12.jpg" alt="" />
            </div>
        </div>
        
    </div>
</body>
</html>
复制代码

方法2.1:原生JS瀑布流

实际项目中需要根据具体情况做相应的改动 大致情况有:

  • 瀑布流整体的宽度(下面的演示代码宽度为全屏)
  • 内部item元素的高度(有些项目item里不单单就是一张图片,还有文本。下面的演示代码只含一张图片)
  • 实际请求数据时,图片还没加载完就执行js,导致获取的宽高都为0;需要利用img.onload来判断图片是否加载完毕,再执行位置的计算
  • css动画效果

演示代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JS实现瀑布流1</title>
    <!-- 样式部分 -->
    <style>
        .container{
            position:relative;
        }
        .item{
            overflow: hidden;
            position: absolute;
        }
        .item img {
            width: 95%;
        }
    </style>
</head>
<body>
    <!-- html 部分 -->
    <div id="container">
        <div class="item">
            <img  src="img/bg1.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg2.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg3.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg4.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg5.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg6.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg7.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg8.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg9.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg10.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg11.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg12.jpg" alt="" />
        </div>
    </div>
    <!-- js 部分 -->
    <script>
        // 封装成一个函数
        function waterFall() {
            var container = document.getElementById('container');
            var items = container.children;
            var columns = 5; //5列

            //根据屏幕宽度和设定的列数, 计算出实际item的宽度
            var pageWidth = getClient().width;
            var itemWidth = parseInt(pageWidth/columns); 

            // 存储每列当前的高度
            var arr = []; 

            for (var i = 0; i < items.length; i++) {
                // 设置每个item的宽度
                items[i].style.width=itemWidth+'px';

                // 根据实际图片的宽高比列 计算出实际item的高度
                var height = items[i].querySelector("img").height;
                var width = items[i].querySelector("img").width;
                var bi = itemWidth/width;  //获取缩小的比值
                var itemHeight = parseInt(height*bi); //图片的高度*比值 = item的高度
                
                // 第一行,item的top都为0,特殊处理
                if (i < columns) {
                    items[i].style.top = 0;
                    items[i].style.left = itemWidth * i + 'px';
                    arr.push(itemHeight);

                } else {
                    // 其他行:通过寻找arr数组里的最小高度,来计算item的位置

                    // 找到arr数组中最小高度和它的索引
                    var minHeight = arr[0];
                    var index = 0;
                    for (var j = 0; j < arr.length; j++) {
                        if (minHeight > arr[j]) {
                            minHeight = arr[j];
                            index = j;
                        }
                    }
                    // 设置该item的位置
                    // top值就是最小列的高度 
                    items[i].style.top = arr[index] + 'px';
                    // left值就是最小列距离左边的距离
                    items[i].style.left = items[index].offsetLeft + 'px';

                    // 修改最小列的高度 
                    // 最小列的高度 = 当前自己的高度 + 拼接过来的高度 
                    arr[index] = arr[index] + itemHeight;
                }
            }
        }
     
        // 获取屏幕宽高  clientWidth 处理兼容性 
        function getClient() {
            return {
                width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
                height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
            }
        }
        // 返回垂直方向滚动的像素  scrollTop兼容性处理 
        function getScrollTop() {
            return window.pageYOffset || document.documentElement.scrollTop;
        }

        window.onload = function() {
            // 一进来就调用一次
            waterFall();
        };

        // 页面尺寸改变时实时触发waterFall()函数,重新排列
        window.onresize = function() {
            waterFall();
        };

        // 当滚动到最后item的时候,模拟ajax请求获取数据,动态添加到html中
        window.onscroll = function() {
            var container = document.getElementById('container');
            var items = container.children;
            // 当屏幕高度+滚动高度 >= 最后一个item的距外层container的高度, 即滚动到最后了
            if (getClient().height + getScrollTop() >= items[items.length - 1].offsetTop) {
                // 模拟 ajax 获取的数据 
                var datas = [
                    "img/bg13.jpg",
                    "img/bg14.jpg",
                    "img/bg15.jpg",
                    "img/bg16.jpg",
                    "img/bg17.jpg",
                    "img/bg1.jpg",
                    "img/bg2.jpg",
                    "img/bg3.jpg",
                    "img/bg4.jpeg",
                ];
                // 循环获取到的数据,添加到hmtl中
                for (var i = 0; i < datas.length; i++) {
                    var div = document.createElement("div");
                    div.className = "item";
                    div.innerHTML = '<img src="' + datas[i] + '" alt="">';
                    container.appendChild(div);
                };

                // 重新排列一下
                waterFall();
            }

        };
    
    </script>
</body>
</html>
复制代码

方法2.1:JQ瀑布流

实际项目中需要根据具体情况做相应的改动 大致情况有:

  • 瀑布流整体的宽度(下面的演示代码宽度为全屏)
  • 内部item元素的高度(有些项目item里不单单就是一张图片,还有文本。下面的演示代码只含一张图片)
  • 实际请求数据时,图片还没加载完就执行js,导致获取的宽高都为0;需要利用img.onload来判断图片是否加载完毕,再执行位置的计算
  • css动画效果
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JQ实现瀑布流布局</title>
    <style>
        .container{
            width: 100%;
            position:relative;
        }
        .item{
            overflow: hidden;
            position: absolute;
        }
        .item img {
            width: 95%;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item">
            <img  src="img/bg1.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg2.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg3.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg4.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg5.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg6.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg7.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg8.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg9.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg10.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg11.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg12.jpg" alt="" />
        </div>
    </div>
    <script src="js/jquery-3.4.1.min.js"></script>
    <script>
    
        function waterFall() {
            // 1- 确定图片的宽度 - 滚动条宽度
            var pageWidth = getClient().width-8;
            var columns = 5; //3列
            var itemWidth = parseInt(pageWidth/columns); //得到item的宽度
            $(".item").width(itemWidth); //设置到item的宽度
            
            var arr = [];

            $(".container .item").each(function(i){
                var height = $(this).find("img").height();
                var width = $(this).find("img").width();
                var bi = itemWidth/width; //获取缩小的比值
                var boxheight = parseInt(height*bi); //图片的高度*比值 = item的高度

                if (i < columns) {
                    // 2- 确定第一行
                    $(this).css({
                        top:0,
                        left:(itemWidth) * i
                    });
                    arr.push(boxheight);

                } else {
                    // 其他行
                    // 3- 找到数组中最小高度  和 它的索引
                    var minHeight = arr[0];
                    var index = 0;
                    for (var j = 0; j < arr.length; j++) {
                        if (minHeight > arr[j]) {
                            minHeight = arr[j];
                            index = j;
                        }
                    }

                    // 4- 设置下一行的第一个盒子位置
                    // top值就是最小列的高度 
                    $(this).css({
                        top:arr[index],
                        left:$(".container .item").eq(index).css("left")
                    });

                    // 5- 修改最小列的高度 
                    // 最小列的高度 = 当前自己的高度 + 拼接过来的高度
                    arr[index] = arr[index] + boxheight;
                }
            });
        }

        //clientWidth 处理兼容性
        function getClient() {
            return {
                width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
                height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
            }
        }

        // 返回垂直方向滚动的像素  scrollTop兼容性处理 
        function getScrollTop() {
            return window.pageYOffset || document.documentElement.scrollTop;
        }

        // 页面尺寸改变时实时触发
        window.onresize = function() {
            //重新定义瀑布流
            waterFall();
        };

        //初始化
        window.onload = function(){
            //实现瀑布流
            waterFall();
        }

          // 当滚动到最后item的时候,模拟ajax请求获取数据,动态添加到html中
          window.onscroll = function() {
            var container = $(".container");
            var items =$(".container .item");
            // 当屏幕高度+滚动高度 >= 最后一个item的距外层container的高度, 即滚动到最后了
            if (getClient().height + getScrollTop() >= items[items.length - 1].offsetTop) {
                // 模拟 ajax 获取的数据 
                var datas = [
                    "img/bg13.jpg",
                    "img/bg14.jpg",
                    "img/bg15.jpg",
                    "img/bg16.jpg",
                    "img/bg17.jpg",
                    "img/bg1.jpg",
                    "img/bg2.jpg",
                    "img/bg3.jpg",
                    "img/bg4.jpeg",
                ];
                // 循环获取到的数据,添加到hmtl中
                for (var i = 0; i < datas.length; i++) {
                    container.append(`<div class="item"><img src=${datas[i]}></div>`);
                };

                // 重新排列一下
                waterFall();
            }

        };
    
    </script>
</body>
</html>
复制代码

方法3.1:使用插件:Masonry

动态加载功能,后续添加。。。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Masonry插件使用</title>
    <style>
        .grid{
            width:1040px;
            margin: 0 auto;
        }
        .grid-item{
            width:200px;
            margin-bottom: 10px;
        }
        .grid-item img{
            width:100%;
        }
    </style>
   
</head>
<body>
    <div class="grid">
        <div class="grid-item">
            <img  src="img/bg1.jpg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg2.jpg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg3.jpg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg4.jpeg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg5.jpg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg6.jpg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg7.jpg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg8.jpeg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg9.jpg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg10.jpg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg11.jpg" alt="" />
        </div>
        <div class="grid-item">
            <img  src="img/bg12.jpg" alt="" />
        </div>
    </div>
    <script src="js/jquery-3.4.1.min.js"></script>
    <script src="js/masonry.pkgd.min.js"></script>
    <script>
        $('.grid').masonry({
            // options
            itemSelector: '.grid-item',
            columnWidth: 200,
            gutter:10, // 网格水平方向边距(即列与列之间的距离)
        });
        
    </script>
</body>
</html>
复制代码
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改