要实现这样的一个成果的, 光用css是flex或者float无奈实现的,

要实现这样的成果,咱们须要用到相对定位,而后用到JavaScript,来计算每个卡片的left和top值

这里实现一个demo

首先创立一个卡片的容器

<div id="main"> </div>

加点款式

 <style> * {            margin: 0;            padding: 0;        }        #main {            width: 1000px;            height: 800px;            background: #ccc;            display: flex;            position: relative;            padding: 10px;            overflow: auto;        }        #main>div {            outline: 1px solid #000;            position: absolute;        } </style>

咱们假如卡片宽度是固定的,默认为100px

随机生成100组卡片数据

 const Container = document.getElementById("main");        let totalWidth = Container.getBoundingClientRect().width        const DefaultWidth = 100;        function getRandom() {            return Math.ceil(((Math.random()) * 50)) + 100        }        function Color() {            let r = Math.ceil(Math.random() * 255);            let g = Math.ceil(Math.random() * 255);            let b = Math.ceil(Math.random() * 255);            return 'rgba(' + r + ',' + g + ',' + b + ',0.8)';        }        let data = [];        for (let i = 0; i < 100; i++) {            data.push({                height: getRandom(),                background: Color(),            })        }

而后遍历这100组数据生成卡片退出到容器中。

首次遍历时,保留下每列的高度,行列信息,

而后第一行填满后,剩下的行从没列的最矮的卡片开始填充残余的卡片

以此逻辑填充完剩下的卡片。

代码逻辑如下

 /* 行列信息*/        let rowColInfos = [];        let currentCol = 0;        let currentRow = 0;        //每行信息排序一次        let isSort = false;        //以后行是否铺满标        let mark = 0;        const frag = document.createDocumentFragment();        for (let d of data) {            let div = document.createElement("div");            div.style.width = DefaultWidth + "px";            div.style.height = d.height + "px";            div.style.backgroundColor = d.background;            frag.append(div);            //第一行,记录当前列的初始数据            if (currentRow === 0) {                heightData[currentCol] = {                    height: d.height,                    row: currentRow,                    col: currentCol,                };                div.style.left = DefaultWidth * currentCol + "px";                div.style.top = 0;                if (DefaultWidth * (currentCol + 1) + DefaultWidth >= totalWidth) {                    currentRow++;                }                else                    currentCol++;            }            else {                //以后每列的高度,从低到高排序                if (!isSort) {                    heightData.sort((d1, d2) => d1.height - d2.height);                    isSort = true;                }                for (let info of heightData) {                    //取以后行数据信息给与以后卡片的地位                    if (info.row + 1 === currentRow) {                        div.style.left = info.col * DefaultWidth + "px";                        div.style.top = info.height + "px";                        info.height += d.height;                        mark++;                        info.row++;                        break;                    }                }                //这行填充斥了,进行下一轮填充                if (mark === heightData.length) {                    mark = 0;                    isSort = false;                    currentRow++;                }            }        }        Container.appendChild(frag);

总结

这里简略实现了固定宽度的卡片主动填充,如果须要扩大,比方

1.加个过渡成果,须要第一次遍历便插入到元素中,第二次遍历扭转元素地位

2.不同宽度,不同高度的自适应,那太简单,须要用到比拟高级的算法,个别不必用到

如果有更好的办法,也可留言交换。