為什么要有瀑布流:
由於div高度不一樣,不管是左浮動還是inline-block,同級的div都會平行顯示(會有空白部分)。
沒有加的效果:
加了瀑布流效果樣子:
瀑布流實現方式:
1. css + js (難點) : 需要通過js計算圖片的位置,進行正確排放,順序不會亂,可持續加載新的數據
2. 純css(簡單) : 數據排序方式是列排序的,當有新的數據持續加載進入不合適,但是性能高、簡單
視頻教程:
# 慕課網的 瀑布流布局教程視頻
https://www.imooc.com/learn/101
第一種方法:
思路: 首先瀑布流的特點是 等寬不等高,需要獲取到盒子的寬度,計算出多少列,拿到第一行每個盒子的高度數組,從第二行第一個開始,依次找最矮盒子的高度位置進行位置偏移即可,之后累加列高度,從而使整個頁面的盒子緊挨。

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 body{ 8 padding: 0; 9 margin: 0; 10 } 11 #pb_main{ 12 position: relative; 13 } 14 #pb_main .box{ 15 width: 15.6%; 16 padding: 0.5em; 17 float: left; 18 } 19 #pb_main .box .box-content{ 20 border: 1px solid #aaa; 21 border-radius: 1em; 22 overflow: hidden; 23 box-shadow: 0 0 20px #ccc; 24 } 25 #pb_main .box .box-content:hover{ 26 cursor: pointer; 27 transition: 0.2s; 28 transform: translateY(-5px); 29 } 30 #pb_main .box .box-content .picture{ 31 } 32 #pb_main .box .box-content .picture img{ 33 width: 100%; 34 } 35 #pb_main .box .box-content .pb-text{ 36 padding: 5px; 37 } 38 39 </style> 40 </head> 41 <body> 42 43 <div id="pb_main"> 44 45 </div> 46 47 <script> 48 49 let img_index = 0; 50 51 // 批量添加一些,第一批測試數據 52 function addElement(count) { 53 let pb_main = document.getElementById('pb_main'); 54 for (let i=0;i<count;i++,img_index++){ 55 let box = document.createElement('div'); 56 box.classList.add('box'); 57 let boxContent = document.createElement('div'); 58 boxContent.classList.add('box-content'); 59 let picture = document.createElement('div'); 60 picture.classList.add('picture'); 61 let img = document.createElement('img'); 62 img.src = `image/${img_index+1}.jpg`; 63 let pgText = document.createElement('div'); 64 pgText.classList.add('pb-text'); 65 pgText.innerText = `${(i+1)*123}測試標題~~`; 66 67 picture.appendChild(img); 68 boxContent.appendChild(picture); 69 boxContent.appendChild(pgText); 70 box.appendChild(boxContent); 71 pb_main.appendChild(box); 72 73 // 每加載好一個圖片,就執行重新布局一遍。 74 img.onload = function () { 75 waterfall('pb_main', 'box') 76 }; 77 } 78 79 } 80 81 function getArrayIndex(arr, value) { 82 for (let i=0;i<arr.length;i++){ 83 if (arr[i] === value){ 84 return i; 85 } 86 } 87 } 88 89 // 排版瀑布流,思路:第二行第一個元素跟着第一行高度最矮的,依次類推。 90 function waterfall(parent, box){ 91 // 獲取標簽對象 92 let Parent = document.getElementById(parent); 93 let boxes = Parent.getElementsByClassName(box); 94 // 獲取盒子的寬,瀑布流的特點:等寬不等高 95 let boxWidth = boxes[0].offsetWidth; 96 // 獲取屏幕能有幾列盒子數 97 let cols = Math.floor(document.body.clientWidth / boxWidth); 98 // 存放列高 99 let temp = []; 100 // 循環修改盒子的位置 101 for (let i=0;i<boxes.length;i++){ 102 // 第一行不做位置修改,要記錄高度,再后續行修改完位置后需要累加高度 103 // 第二行、第三行。。。根據temp表里記錄的高度,找出最矮的依次排序到下面 104 if (i < cols){ 105 temp.push(boxes[i].offsetHeight); 106 }else{ 107 // 查找最小的高度 108 let height = Math.min(...temp); 109 // 最小高度的索引 110 let index = getArrayIndex(temp, height); 111 // 修改當前循環盒子的頁面位置 112 boxes[i].style.position = "absolute"; 113 boxes[i].style.left = `${boxWidth * index}px`; 114 boxes[i].style.top = `${height}px`; 115 // 累加高度列表的該索引的值 116 temp[index] += boxes[i].offsetHeight; 117 // 設置父級高度,這樣布局不會亂,由於左浮動后沒有高度 118 Parent.style.height = `${Math.max(...temp)}px` 119 } 120 } 121 } 122 123 // 檢查高度是否超過 124 function checkScrollTop(parent, box){ 125 // 滾動條頂部的值 126 let top = document.documentElement.scrollTop||document.body.scrollTop; 127 let screen_height = document.documentElement.clientHeight || document.body.clientHeight; 128 // 獲取標簽對象 129 let Parent = document.getElementById(parent); 130 let boxes = Parent.getElementsByClassName(box); 131 let last_box = boxes[boxes.length-1]; 132 let last_box_h = last_box.offsetTop + Math.floor(last_box.offsetHeight / 2); 133 console.log(`最后盒子頂部距離 + 它一半高度:${last_box_h}, 頂部距離加屏幕高度是: ${top+screen_height}`); 134 // 判斷頂部滾輪+屏幕高度是否大於這個最后盒子距離+一半高度, 大於表示要加載新內容了 135 return (top+screen_height) > last_box_h ? true:false; 136 } 137 138 window.onload = function (){ 139 // 添加首次的測試元素,需要大於一屏幕 140 addElement(20); 141 // 監測滾動條 142 window.onscroll = function () { 143 // 判讀是否需要加載新內容 144 if (checkScrollTop('pb_main', 'box')){ 145 addElement(10); 146 // 由於圖片有限,重置 147 if (img_index >= 29){ 148 img_index = 0; 149 } 150 } 151 } 152 } 153 154 </script> 155 </body> 156 </html>
// 圖片素材自己找點(30張圖片),就可以看運行效果了
第二種方法:
.my-card-wrapper{ -moz-column-count:2; -webkit-column-count:2; column-count:2; -moz-column-gap:0; -webkit-column-gap:0; padding-top: 0.5em; } .my-card{ border: 1px solid #cccccc; padding: 8px; border-radius: 10px; -moz-page-break-inside: avoid; -webkit-column-break-inside: avoid; break-inside: avoid; margin: 0 0.5em 0.5em; }
// 斜體加粗部分是關鍵代碼
代碼解釋:
column-count # 流式布局幾列顯示
-moz-column-count:2; # 為了適配不同瀏覽器
-webkit-column-count:2; # 為了適配不同瀏覽器
-webkit-column-gap:0; # 列之前的間隔,有默認間隔值,為了不影響效果,我改的0,自己做邊距
break-inside: avoid; # 防止多列布局,分頁媒體和多區域上下文中的意外中斷?? 不懂設置上即可