前言
大家好!👋
在这个数字世界里,瀑布流布局以其独特的魅力成为了展示内容的一种流行方式。它不仅让页面看起来更加生动有趣,还能适应不同设备的屏幕大小。今天,就让我们一起探索如何用前端技术打造一个属于自己的瀑布流布局。
样式展示:
正文
知识点
id&class
id 是页面上唯一的元素标识符,用于指向特定元素或在JavaScript中定位;class 可以被多个元素共享,用于应用一组样式。id 选择器用 # 表示,class 选择器用 . 表示。
浮动布局
- 脱离文档流:使用
float属性的元素会脱离正常的文档流,这意味着它不会占据文档流中的正常位置。 - 左右浮动:通过设置
float: left;或float: right;,元素可以向左或向右浮动。 - 环绕内容:浮动元素周围的文本和其他元素可以环绕浮动元素,形成多列布局。
- 清除浮动:使用
clear属性可以清除浮动的影响,防止元素被浮动元素覆盖。 - 布局控制:浮动布局可以用于控制元素的布局,但需要小心处理,以避免布局问题。
.offsetWidth
返回一个元素的布局宽度,包括元素的边框(border)、内边距(padding)和内容区域(content area),但不包括外边距(margin)
offsetWidth 返回的是一个整数值,表示元素的宽度,单位是像素(px)、
摆放图片位置
-
ccontent[i].style.position = 'absolute';- 这行代码将图片元素(
ccontent[i])的position属性设置为absolute。所以该元素将从文档流中脱离出来,并且可以使用top、right、bottom、left等属性来绝对定位它的位置。
- 这行代码将图片元素(
-
ccontent[i].style.top = minHeight + 'px';- 设置图片元素的
top属性,使其垂直位置相对于包含它的最近的已定位(非 static)祖先元素。minHeight是当前找到的最小高度值,这通常是前一行中最低的列的高度。通过将图片放在这个高度,新的图片将被放置在前一行的最低点下方。
- 设置图片元素的
-
ccontent[i].style.left = ccontent[minIndex].offsetLeft + 'px';- 同top,
ccontent[minIndex].offsetLeft是前一行中高度最低的列的第一个元素的水平偏移量。通过使用这个值,新的图片将被放置在前一行最矮列的开始位置,从而实现水平对齐。
- 同top,
设置容器宽度
cparent.style.width = {imgWidth *num}px
用js代码中的例子进行解释:
- 这里使用模板字符串将
imgWidth和num的值嵌入到字符串中,计算出容器的总宽度。 - 设置
cparent元素的style.width属性,将其宽度设置为计算出的结果,单位是像素(px)
js代码核心部分
var BoxHeightArr = [];
for (let i = 0; i < ccontent.length; i++) {
if (i < num) {
BoxHeightArr[i] = ccontent[i].offsetHeight;
} else {
var minHeight = Math.min.apply(null, BoxHeightArr);
var minIndex = BoxHeightArr.indexOf(minHeight);
ccontent[i].style.position = 'absolute';
ccontent[i].style.top = minHeight + 'px';
ccontent[i].style.left = ccontent[minIndex].offsetLeft + 'px';
BoxHeightArr[minIndex] += ccontent[i].offsetHeight;
}
}
这段JavaScript代码的作用是遍历所有的图片元素,计算并设置每张图片的确切位置。下面是对代码的逐行解释:
-
var BoxHeightArr = [];- 初始化一个数组
BoxHeightArr,存储每一列最矮矮子的高度。
- 初始化一个数组
-
for (let i = 0; i < ccontent.length; i++) { ... }- 循环遍历所有的图片元素(
ccontent数组中的元素)。
- 循环遍历所有的图片元素(
-
if (i < num) { ... }- 条件判断,如果当前索引
i小于每行可以放置的图片数量num,则执行。
- 条件判断,如果当前索引
-
BoxHeightArr[i] = ccontent[i].offsetHeight;- 将第一行的图片元素的高度赋值给
BoxHeightArr数组对应的位置。因为第一行的图片直接显示,无需进行位置计算。
- 将第一行的图片元素的高度赋值给
-
var minHeight = Math.min.apply(null, BoxHeightArr);- 使用
Math.min函数和apply方法找出BoxHeightArr数组中的最小值,即当前最矮的列的高度。
- 使用
-
var minIndex = BoxHeightArr.indexOf(minHeight);- 这行代码获取最小高度在
BoxHeightArr数组中的索引,即最矮列的位置。
- 这行代码获取最小高度在
-
ccontent[i].style.position = 'absolute';- 将当前图片元素的CSS
position属性设置为absolute,这样可以通过top和left属性来绝对定位它。
- 将当前图片元素的CSS
-
ccontent[i].style.top = minHeight + 'px';- 设置
top属性,使其垂直位置位于最矮列的当前高度之上。
- 设置
-
ccontent[i].style.left = ccontent[minIndex].offsetLeft + 'px';- 设置
left属性,使其水平位置与最矮列的第一个图片元素的左边距相同,实现水平对齐。
- 设置
-
BoxHeightArr[minIndex] += ccontent[i].offsetHeight;
- 更新最矮列的高度,将当前图片的高度加到 `BoxHeightArr` 数组对应索引的位置。
这段代码的目的是实现一个动态的图片布局,其中图片会根据前一行中最矮的列的高度来确定自己的位置,从而创建出视觉上更加平衡和美观的瀑布流效果。
HTML
HTML主要代码
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
#container {
position: relative;
}
.box {
float: left;
padding: 5px;
}
.box-img {
width: 150px;
padding: 5px;
border: 4px solid #debe80;
}
img {
width: 100%;/* box-img的100% 高也自动收缩,图片不失真*/
}
</style>
</head>
<body>
<div id="container">
<div class="box">
<div class="box-img">
<img src="./img/1.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/2.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/3.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/4.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/5.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/6.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/7.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/8.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/9.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/10.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/1.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/2.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/3.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/4.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/5.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/6.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/7.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/8.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/9.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/10.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./img/11.webp" alt="">
</div>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
JS
javascript部分是大头,写js的主要目标就是,获取到用户屏幕的宽度,这样就能决定一行能放几张图,再者是操作下一张图,放到上一行最矮的列下面
JavaScript完整代码:
function imgLocation(parent, content) {
var cparent = document.getElementById(parent);//parent在这里相当于'container'
// 有多少张图片
// var ccontent = document.querySelectorAll('.box');//把类名为box全部获取,但可能别的类名也为box所以这里不采用
// var ccontent = document.querySelectorAll('#container .box');//取到的是container的box,好用!但是我们选择手搓,看辅助函数getChildElement()
var ccontent = getChildElement(cparent, content);
// 获取每一个box的宽度
var imgWidth = ccontent[0].offsetWidth;//获取容器的宽度,任何标签的自带的属性
// 屏幕一行能放下几个图片 向下取整
var num = Math.floor(document.documentElement.clientWidth / imgWidth);
//设置container的宽度
cparent.style.width = `{imgWidth *num}px`;
// 要操作的是哪一张 num+1,取到每一列的高度
var BoxHeightArr = [];
for (let i = 0; i < ccontent.length; i++) {
if (i < num) {
// 第一行
BoxHeightArr[i] = ccontent[i].offsetHeight;
} else {
// 需要操作的部分,下一行了
var minHeight = Math.min.apply(null, BoxHeightArr);
var minIndex = BoxHeightArr.indexOf(minHeight);
//摆放图片的位置
ccontent[i].style.position = 'absolute';
ccontent[i].style.top = minHeight + 'px';
ccontent[i].style.left = ccontent[minIndex].offsetLeft + 'px';
// 更新这一列的高度
BoxHeightArr[minIndex] += ccontent[i].offsetHeight;
}
}
}
//辅助函数getChildElement()
function getChildElement(parent, child) {
// 获取parent中所有的child
var childArr = [];
// 返回的是数组结构
var allChild = parent.getElementsByTagName('*');//parent里的所有的标签
// 挑出所有Child中的box
for (let i = 0; i < allChild.length; i++) {
if (allChild[i].className == child) {//判断类名是否含有形参child
childArr.push(allChild[i]);//尾部增加进去
}
}
return childArr;
}
imgLocation('container', 'box');
结语
希望你喜欢这次的分享,也许这些小技巧能给你的项目带来一些灵感。如果你有任何问题或建议,欢迎私信留言!期待与你的每一次交流,让再次感谢你的阅读,我们下次见!💬👋