1.js
实现思路:
设定每一列盒子的宽度
获取当前窗口的总宽度,从而根据盒子宽度去分成几列
获取所有盒子的元素,定义一个空数组来保存高度
遍历所有容器,开始判断 当页面加载完成,或页面宽度发生变化时,调用函数。
如果当前处于第一行时: 保存当前元素高度。
如果当前不处于第一行时:进行高度对比,通过遍历循环,拿到最小高度和相对应的索引,设置盒子位置并修改当前索引的高度为当前元素高度。
当页面加载完成,或页面宽度发生变化时,调用函数
具体js代码如下,CSS中父元素要设置position的相对定位,子元素float定位
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="home">
<div class="item">
<div style="height: 200px">JS</div>
</div>
<div class="item">
<div style="height: 100px">2</div>
</div>
<div class="item">
<div style="height: 150px">3</div>
</div>
<div class="item">
<div style="height: 300px">4</div>
</div>
<div class="item">
<div style="height: 120px">5</div>
</div>
<div class="item">
<div style="height: 250px">6</div>
</div>
<div class="item">
<div style="height: 140px">7</div>
</div>
<div class="item">
<div style="height: 190px">8</div>
</div>
<div class="item">
<div style="height: 240px">9</div>
</div>
<div class="item">
<div style="height: 330px">10</div>
</div>
<div class="item">
<div style="height: 110px">11</div>
</div>
<div class="item">
<div style="height: 145px">12</div>
</div>
<div class="item">
<div style="height: 190px">13</div>
</div>
<div class="item">
<div style="height: 245px">14</div>
</div>
</div>
</body>
<style>
#home{
position: relative;
}
.item{
float: left;
box-sizing: border-box;
border: 1px solid red;
text-align: center;
width: 310px;
}
</style>
<script>
function fall() {
const itemWidth = 310;//每一项的宽度
const scrollBarWidth = getScrollbarWidth();//获取滚动条宽度
const pageWidth = window.innerWidth - scrollBarWidth;//当前页面宽度
const column = Math.floor(pageWidth / itemWidth );//实际列数,返回小于这个值的最大整数
console.log(column)
const items = document.querySelectorAll('.item')//获取所有子元素
const heightArr = [];//保存最低高度的空数组
//获取滚动条的宽度
function getScrollbarWidth() {
const oDiv = document.createElement('div')//创建一个div
oDiv.style.cssText = 'width:50px;height:50px;overflowY:scroll'//给div随意设置样式,有滚动条就行
document.body.appendChild(oDiv);//把div添加到body中
const scollbarWidth = oDiv.offsetWidth - oDiv.clientWidth;//最大宽度减可视宽度,获取滚动条
oDiv.remove();//移除创建的div
return scollbarWidth;//返回滚动条宽度
}
//便利所有项目元素
for(let i = 0; i < items.length; i++){
//元素高度
const height = items[i].offsetHeight;
//如果处在第一行,如一共3列,i<3
if (i < column){
//直接设置元素距离上部的位置和距离左边的距离
// items[i].style.cssText = 'top:' + gap + 'px;';
// left:${(itemWidth + gap)*i}px';
//保存当前元素的高度
heightArr.push(height)
}else{
//不是第一行就进行比对
let minHeight = heightArr[0];//先保存第一项高度
let minIndex = 0;//保存第一项索引
for (let j = 0;j < heightArr.length;j++){
//通过循环遍历,拿到高度最小值和最小值的索引
if(minHeight > heightArr[j]){
minHeight = heightArr[j];
minIndex = j;
}
}
//最小值为当前元素设置top,通过索引设置left
items[i].style.cssText = 'position: absolute;' + 'top:' + minHeight + 'px;left:'+ (itemWidth)*minIndex + 'px;';
//修改当前索引高度为当前元素高度
heightArr[minIndex] = minHeight + height;
}
}
}
//页面加载完成调用一次
window.onload = fall;
//页面尺寸改变再次调用
window.onresize = fall;
</script>
</html>实现了横向排列,并且可以随着页面的变化而动态变更列数,方便添加更改数据,且没有兼容性问题。
缺点;代码繁琐,性能消耗大
2.flex布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="home">
<div style="height: 100px">flex</div>
<div style="height: 200px">2</div>
<div style="height: 350px">3</div>
<div style="height: 100px">4</div>
<div style="height: 100px">5</div>
<div style="height: 300px">6</div>
<div style="height: 200px">7</div>
<div style="height: 150px">8</div>
</div>
</body>
<style>
.home{
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 100%;
height: 500px;
}
.home div{
width: 25%;
border: 1px solid red;
text-align: center;
box-sizing: border-box;
}
</style>
</html>flex布局中使用column纵向排列,给定容器具体高度后设置warp属性就会自动换列。
缺点:只能纵向开始排列,并且不给定父容器高度它将会一直向下排列不会换列,不方便增添更改数据
3.多栏布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="home">
<div style="height: 200px">多栏</div>
<div style="height: 300px">2</div>
<div style="height: 150px">3</div>
<div style="height: 300px">4</div>
<div style="height: 300px">5</div>
<div style="height: 200px">6</div>
<div style="height: 100px">7</div>
<div style="height: 350px">8</div>
</div>
</body>
<style>
.home{
column-count: 4;
column-gap: 0;
}
.home div{
text-align: center;
box-sizing: border-box;
border: 1px solid red;
break-inside:avoid /*控制文本块分解成单独的列,以免项目列表的内容跨列*/
}
</style>
</html>多栏布局,给定列数即可,子元素一定要给break-inside:avoid属性,不然可能发生盒子一半在第一列,一半在第二列。
缺点:会出现顺序错乱问题,有时横向,有时纵向
IE9及更早 IE 版本浏览器不支持 column-count 属性
4.grid布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="home">
<div >grid</div>
<div >2</div>
<div >3</div>
<div >4</div>
<div >5</div>
<div >6</div>
<div >7</div>
</div>
</body>
<style>
.home div{
width: 100%;
border: 1px solid red;
text-align: center;
box-sizing: border-box;
}
.home{
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(3,1fr);
grid-auto-rows: 10px;/*每一格的高度*/
}
.home div:nth-of-type(3n+1) {
grid-row: auto / span 5;
}
.home div:nth-of-type(3n+2) {
grid-row: auto / span 6;
}
.home div:nth-of-type(3n+3) {
grid-row: auto / span 8;
}
</style>
</html>网格布局(Grid)是最强大的 CSS 布局方式, 它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,可近似的看成是二维布局。
与上述两种纯CSS方法不同的是它实现了瀑布流的横向排列
缺点:虽然实现了横向排列,每个盒子高度需要手动设置占了几列不能自适应
属于面向未来的CSS布局,兼容性差,暂不支持IE