要实现这样的一个成果的,光用 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. 不同宽度,不同高度的自适应,那太简单,须要用到比拟高级的算法,个别不必用到
如果有更好的办法,也可留言交换。