瀑布流
布局
瀑布流布局(Waterfall Layout)是一种常见的网页布局方式,通常用于展示图片或卡片式内容。其特点是将内容以多列的方式依次排列,犹如瀑布般从上至下流动。这种布局能够有效利用页面空间,展示更多内容,并且在移动设备上也有良好的适应性。
瀑布流实现的方式可以使用纯CSS,也可以使用js实现,如何选取取决于需求,这几种方法各有优略,如何选取取决于需求。以下案例均采用如下的html代码
ini
<div class="waterFull" id="con">
<div class="item">
<img src="../1.jpeg" alt="">
</div>
<div class="item">
<img src="../2.jpg" alt="">
</div>
<div class="item">
<img src="../3.jpg" alt="">
</div>
<div class="item">
<img src="../4.jpg" alt="">
</div>
<div class="item">
<img src="../5.jpg" alt="">
</div>
<div class="item">
<img src="../6.jpg" alt="">
</div>
<div class="item">
<img src="../7.jpg" alt="">
</div>
<div class="item">
<img src="../8.jpg" alt="">
</div>
<div class="item">
<img src="../9.jpg" alt="">
</div>
<div class="item">
<img src="../10.jpg" alt="">
</div>
<div class="item">
<img src="../11.jpg" alt="">
</div>
<div class="item">
<img src="../12.jpg" alt="">
</div>
<div class="item">
<img src="../13.jpg" alt="">
</div>
<div class="item">
<img src="../14.jpg" alt="">
</div>
<div class="item">
<img src="../15.jpg" alt="">
</div>
</div>
使用column
属性
实现代码
xml
<style>
.waterFull{
column-count: 4;
column-gap: 0;
}
.item img{
width: 100%;
}
</style>
实现效果
使用column-count属性设置一个盒子分为多列展示数据,使用column-gap属性设置每个元素之间的间距。
- 优点
- 实现代码简单,只需要给父元素两行代码
- 列数不会随着浏览器的宽度变化而变化,例如:指定列数为4就只能显示4列
- 缺点
- 图片是自上而下一列一列实现的布局,如果我们需要动态的添加一些业务,那么新加入的图片将不会加入页面的最低端,不符合我们的业务需求
使用flex
布局
实现代码
css
.waterFull{
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 1600px;
}
.item{
width: 25%;
}
.item img{
width: 100%;
}
实现效果
使用弹性盒子,给弹性元素指定列排列,然后给每个元素指定宽度(宽度设置为(1/列数)如果想要排成4列就设置成25%,如果想要排成5列就设置成20%以此类推)。
由于设置为列排列,当元素的累计高度没有超过指定的高度时,首先会在第一个列上堆叠元素
只要我们元素的数量合适,能够在指定的高度下填满4列,也是能实现瀑布流布局的
优化
css
.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失效。
总结:
优点: 同样相对简单 如果每列数量差图片数量相同,则可以实现新的图片显示在最下方的业务 缺点: 列数不会随着浏览器的宽度而改变 需要指定高度,并且在每一列放置合适数量的图片。 如果没有给容器设置固定宽度,则当容器宽度缩小时,图片的宽度相应的缩小,由于图片的高度是auto,即按图片原比例展示,因此图片高度会相应减少,由于高度指定,图片数量固定,则可能会出现图片占不满列数的情况,,具体问题如下图
JS
方法实现
原理:通过JS,根据每个图片的宽度计算出需要放置多少行,将所有图片设置绝对定位,逐一计算出该图片所在的top和left进行定位 实现代码
css
.container{
position: relative;
}
.item{
width: 200px;
height: auto;
position: absolute;
}
.item img{
width: 100%;
}
ini
//当页面加载的时候调用
window.onload = function () {
//页面初始化调用
waterFull()
//每次页面改变大小调用
window.onresize = waterFull
}
function waterFull() {
// 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
}
}
}
为什么每次都要将图片放置在高度最小的列上呢?
因为图片高度不一的情况,如果按下标顺序一个一个排列,最终虽然每一列上图片的数量是一样的,但是显示的高度可能相差甚远,因此选择将每个图片放在高度最小的列上让每一列的总高度不会相差太大。
当浏览器缩放的时候,图片列数自动匹配。
火狐浏览器使用网格布局
实现代码
xml
<style>
img {
width: 100px;
}
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: masonry;
grid-gap: 10px;
}
</style>
ini
<div class="container">
<img src="/1.jpeg" alt="" />
<img src="/2.jpg" alt="" />
<img src="/3.jpg" alt="" />
<img src="/4.jpg" alt="" />
<img src="/5.jpg" alt="" />
<img src="/6.jpg" alt="" />
<img src="/7.jpg" alt="" />
<img src="/8.jpg" alt="" />
<img src="/9.jpg" alt="" />
<img src="/10.jpg" alt="" />
<img src="/11.jpg" alt="" />
</div>
其他浏览器显示内容
火狐浏览器显示内容
在火狐浏览中搜索about:config ,通过设置layout.css.grid-template-masonry-value.enabled属性,默认为false,修改true之后也能实现瀑布流布局