方法總結:
方法一:純CSS佈局
缺點:
每個item是從上到下排列的。如果需要動態加載item,(⊙o⊙)…那真是糟糕透頂!
這個就瞭解瞭解,實際項目中不會這樣寫的。
方法二:JS計算位置
利用絕對定位absolute
,通過JS計算每個item的的top
和left
值
實際項目中圖片的寬高一般是由後端返回過來。這樣前端就不需要計算圖片寬高,用戶體驗會更好!
總之,具體問題具體分析,萬一後端沒返回寬高的勒 (︶︹︺)
方法三: 使用別人寫的插件
方法1.1:multi-column多列布局瀑布流
演示代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>multi-columns瀑布流佈局</title>
<style>
.container {
margin: 0 auto;
width: 1000px;
column-count: 5; /* 列數 */
column-gap: 20px; /* 列間距 */
}
.item {
margin-bottom: 10px;
/* 防止多列布局,分頁媒體和多區域上下文中的意外中斷 */
break-inside: avoid;
}
.item img{
width: 100%;
height:100%;
}
</style>
</head>
<body>
<div class="container">
<div class="item">
<img src="img/bg1.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg2.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg3.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg4.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg5.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg6.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg7.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg8.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg9.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg10.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg11.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg12.jpg" alt="" />
</div>
</div>
</body>
</html>
方法1.2:Flex彈性佈局瀑布流
演示代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Flexbox瀑布流佈局</title>
<style>
.wrapper{
display: flex;
flex-direction: row; /* 每列container 水平排列*/
justify-content: space-between; /* 兩端對齊,間隔相等*/
margin: 0 auto; /* 整體居中 */
width:1000px;
}
.container{
width:240px;
}
.item{
margin-bottom:10px;
}
.item img{
width:100%;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="container">
<div class="item">
<img src="img/bg1.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg2.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg3.jpg" alt="" />
</div>
</div>
<div class="container">
<div class="item">
<img src="img/bg4.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg5.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg6.jpg" alt="" />
</div>
</div>
<div class="container">
<div class="item">
<img src="img/bg7.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg8.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg9.jpg" alt="" />
</div>
</div>
<div class="container">
<div class="item">
<img src="img/bg10.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg11.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg12.jpg" alt="" />
</div>
</div>
</div>
</body>
</html>
方法2.1:原生JS瀑布流
實際項目中需要根據具體情況做相應的改動
大致情況有:
- 瀑布流整體的寬度(下面的演示代碼寬度爲全屏)
- 內部
item
元素的高度(有些項目item
裏不單單就是一張圖片,還有文本。下面的演示代碼只含一張圖片) - 實際請求數據時,圖片還沒加載完就執行
js
,導致獲取的寬高都爲0;需要利用img.onload
來判斷圖片是否加載完畢,再執行位置的計算 - css動畫效果
演示代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JS實現瀑布流1</title>
<!-- 樣式部分 -->
<style>
.container{
position:relative;
}
.item{
overflow: hidden;
position: absolute;
}
.item img {
width: 95%;
}
</style>
</head>
<body>
<!-- html 部分 -->
<div id="container">
<div class="item">
<img src="img/bg1.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg2.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg3.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg4.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg5.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg6.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg7.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg8.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg9.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg10.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg11.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg12.jpg" alt="" />
</div>
</div>
<!-- js 部分 -->
<script>
// 封裝成一個函數
function waterFall() {
var container = document.getElementById('container');
var items = container.children;
var columns = 5; //5列
//根據屏幕寬度和設定的列數, 計算出實際item的寬度
var pageWidth = getClient().width;
var itemWidth = parseInt(pageWidth/columns);
// 存儲每列當前的高度
var arr = [];
for (var i = 0; i < items.length; i++) {
// 設置每個item的寬度
items[i].style.width=itemWidth+'px';
// 根據實際圖片的寬高比列 計算出實際item的高度
var height = items[i].querySelector("img").height;
var width = items[i].querySelector("img").width;
var bi = itemWidth/width; //獲取縮小的比值
var itemHeight = parseInt(height*bi); //圖片的高度*比值 = item的高度
// 第一行,item的top都爲0,特殊處理
if (i < columns) {
items[i].style.top = 0;
items[i].style.left = itemWidth * i + 'px';
arr.push(itemHeight);
} else {
// 其他行:通過尋找arr數組裏的最小高度,來計算item的位置
// 找到arr數組中最小高度和它的索引
var minHeight = arr[0];
var index = 0;
for (var j = 0; j < arr.length; j++) {
if (minHeight > arr[j]) {
minHeight = arr[j];
index = j;
}
}
// 設置該item的位置
// top值就是最小列的高度
items[i].style.top = arr[index] + 'px';
// left值就是最小列距離左邊的距離
items[i].style.left = items[index].offsetLeft + 'px';
// 修改最小列的高度
// 最小列的高度 = 當前自己的高度 + 拼接過來的高度
arr[index] = arr[index] + itemHeight;
}
}
}
// 獲取屏幕寬高 clientWidth 處理兼容性
function getClient() {
return {
width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}
}
// 返回垂直方向滾動的像素 scrollTop兼容性處理
function getScrollTop() {
return window.pageYOffset || document.documentElement.scrollTop;
}
window.onload = function() {
// 一進來就調用一次
waterFall();
};
// 頁面尺寸改變時實時觸發waterFall()函數,重新排列
window.onresize = function() {
waterFall();
};
// 當滾動到最後item的時候,模擬ajax請求獲取數據,動態添加到html中
window.onscroll = function() {
var container = document.getElementById('container');
var items = container.children;
// 當屏幕高度+滾動高度 >= 最後一個item的距外層container的高度, 即滾動到最後了
if (getClient().height + getScrollTop() >= items[items.length - 1].offsetTop) {
// 模擬 ajax 獲取的數據
var datas = [
"img/bg13.jpg",
"img/bg14.jpg",
"img/bg15.jpg",
"img/bg16.jpg",
"img/bg17.jpg",
"img/bg1.jpg",
"img/bg2.jpg",
"img/bg3.jpg",
"img/bg4.jpeg",
];
// 循環獲取到的數據,添加到hmtl中
for (var i = 0; i < datas.length; i++) {
var div = document.createElement("div");
div.className = "item";
div.innerHTML = '<img src="' + datas[i] + '" alt="">';
container.appendChild(div);
};
// 重新排列一下
waterFall();
}
};
</script>
</body>
</html>
方法2.1:JQ瀑布流
實際項目中需要根據具體情況做相應的改動
大致情況有:
- 瀑布流整體的寬度(下面的演示代碼寬度爲全屏)
- 內部
item
元素的高度(有些項目item
裏不單單就是一張圖片,還有文本。下面的演示代碼只含一張圖片) - 實際請求數據時,圖片還沒加載完就執行
js
,導致獲取的寬高都爲0;需要利用img.onload
來判斷圖片是否加載完畢,再執行位置的計算 - css動畫效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JQ實現瀑布流佈局</title>
<style>
.container{
width: 100%;
position:relative;
}
.item{
overflow: hidden;
position: absolute;
}
.item img {
width: 95%;
}
</style>
</head>
<body>
<div class="container">
<div class="item">
<img src="img/bg1.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg2.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg3.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg4.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg5.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg6.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg7.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg8.jpeg" alt="" />
</div>
<div class="item">
<img src="img/bg9.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg10.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg11.jpg" alt="" />
</div>
<div class="item">
<img src="img/bg12.jpg" alt="" />
</div>
</div>
<script src="js/jquery-3.4.1.min.js"></script>
<script>
function waterFall() {
// 1- 確定圖片的寬度 - 滾動條寬度
var pageWidth = getClient().width-8;
var columns = 5; //3列
var itemWidth = parseInt(pageWidth/columns); //得到item的寬度
$(".item").width(itemWidth); //設置到item的寬度
var arr = [];
$(".container .item").each(function(i){
var height = $(this).find("img").height();
var width = $(this).find("img").width();
var bi = itemWidth/width; //獲取縮小的比值
var boxheight = parseInt(height*bi); //圖片的高度*比值 = item的高度
if (i < columns) {
// 2- 確定第一行
$(this).css({
top:0,
left:(itemWidth) * i
});
arr.push(boxheight);
} else {
// 其他行
// 3- 找到數組中最小高度 和 它的索引
var minHeight = arr[0];
var index = 0;
for (var j = 0; j < arr.length; j++) {
if (minHeight > arr[j]) {
minHeight = arr[j];
index = j;
}
}
// 4- 設置下一行的第一個盒子位置
// top值就是最小列的高度
$(this).css({
top:arr[index],
left:$(".container .item").eq(index).css("left")
});
// 5- 修改最小列的高度
// 最小列的高度 = 當前自己的高度 + 拼接過來的高度
arr[index] = arr[index] + boxheight;
}
});
}
//clientWidth 處理兼容性
function getClient() {
return {
width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}
}
// 返回垂直方向滾動的像素 scrollTop兼容性處理
function getScrollTop() {
return window.pageYOffset || document.documentElement.scrollTop;
}
// 頁面尺寸改變時實時觸發
window.onresize = function() {
//重新定義瀑布流
waterFall();
};
//初始化
window.onload = function(){
//實現瀑布流
waterFall();
}
// 當滾動到最後item的時候,模擬ajax請求獲取數據,動態添加到html中
window.onscroll = function() {
var container = $(".container");
var items =$(".container .item");
// 當屏幕高度+滾動高度 >= 最後一個item的距外層container的高度, 即滾動到最後了
if (getClient().height + getScrollTop() >= items[items.length - 1].offsetTop) {
// 模擬 ajax 獲取的數據
var datas = [
"img/bg13.jpg",
"img/bg14.jpg",
"img/bg15.jpg",
"img/bg16.jpg",
"img/bg17.jpg",
"img/bg1.jpg",
"img/bg2.jpg",
"img/bg3.jpg",
"img/bg4.jpeg",
];
// 循環獲取到的數據,添加到hmtl中
for (var i = 0; i < datas.length; i++) {
container.append(`<div class="item"><img src=${datas[i]}></div>`);
};
// 重新排列一下
waterFall();
}
};
</script>
</body>
</html>