記錄一個瀑布流佈局問題的解決過程 最開始使用js實現,將子元素進行絕對定位,根據寬高及順序判斷定位的top與left。 問題:存在新增子元素頁面載入不及時的問題,會出現子元素初始狀態疊加在一起,計算完成後才能正常顯示。 點擊查看代碼 window.onload = () => { /* 傳入wate ...
記錄一個瀑布流佈局問題的解決過程
最開始使用js實現,將子元素進行絕對定位,根據寬高及順序判斷定位的top與left。
問題:存在新增子元素頁面載入不及時的問題,會出現子元素初始狀態疊加在一起,計算完成後才能正常顯示。
點擊查看代碼
window.onload = () => {
/* 傳入waterfall與pic節點,調用函數waterFall */
waterFall('.waterfall', '.cases-item')
}
// column每行個數
// lineSpace列間距
// rowSpace行間距
function waterFall(waterfall, pic, marginTop=20,lineSpace = 0, rowSpace = 40) {
let column=3
let win_w=$(window).width();
if(win_w>1200){
column=3
} else if(win_w<=1200&&win_w>600){
column=2
}
/*waterfallWidth可視視窗waterfall的寬度 */
var waterfallWidth = document.querySelector(waterfall).offsetWidth
/* 計算每個pic的寬度 */
var line = (column - 1) * lineSpace
var picWidth = parseInt((waterfallWidth - line) / column)
/* 獲取所有pic節點 */
var picNode = document.querySelectorAll(pic)
/* 通過for迴圈完成瀑布流的設置 */
var picArr = []
for (var i = 0; i < picNode.length; i++) {
/* 設置每一個pic的寬度 */
picNode[i].style.width = picWidth + 'px'
/* 獲取每一個pic的高 */
// console.log('picNode[i]',picNode[i],picNode[i].clientHeight)
var picHeight = picNode[i].clientHeight
/* 通過判斷,區分第一行和非第一行 */
if (i < column) {
/* 給第一行的進行定位 */
picNode[i].style.top = marginTop
picNode[i].style.left = (picWidth + lineSpace) * i+ 'px'
/* 將獲取的pic的高push到一個數組記錄下來 */
picArr.push(picHeight)
// console.log('picHeight',picHeight)
}else{
/* 在非第一行中,找到數組的最小值 */
var picArrMin=Math.min(...picArr)
// console.log(picArrMin);
/* 獲取最小值的索引 */
var mixIndex=picArr.indexOf(picArrMin)
// console.log(mixIndex);
/* 對非第一行的pic進行定位,top為最小值的高,left為pic寬加行間距乘以最小值的索引 */
picNode[i].style.top=(picArrMin+rowSpace+marginTop+marginTop)+'px'
picNode[i].style.left=(picWidth+lineSpace)*mixIndex+'px'
/* 對數組中的最小值進行修改 */
picArr[mixIndex]+=picHeight+rowSpace
}
}
const boxH=Math.max(...picArr)
$(waterfall).css({height:boxH+'px'})
}
再次嘗試使用css中的column(多列佈局)實現簡單的瀑布流排版。
問題:元素預設為豎向排版,新增子元素不是在最下方更新,用戶體驗不好。
<div class="waterfall">
<div class="item">內容</div>
<div class="item">內容</div>
<div class="item">內容</div>
<div class="item">內容</div>
<div class="item">內容</div>
<div class="item">內容</div>
<div class="item">內容</div>
</div>
css
.waterfall{
column-count: 3;//幾列
column-gap: 10px;//間距
.item{
display: inline-block;
width: 100%;
}
}
再次更換為另一種方法,使用flex佈局實現,結合css中的:nth-child() 和 order屬性,將子元素橫向排列。
但需要為父元素固定高度,才能達到效果,最終使用flex佈局,結合js為父元素的高度賦值,解決了問題。
當添加子元素時,再次調用獲取高度方法,更新父元素高度即可。
佈局同上
css
.waterfall{
display: flex;
/* 讓內容按列縱向展示 */
// flex-flow: column wrap;
flex-direction:column;
flex-wrap: wrap;
height: 5000px;//初始高度,防止在腳本未載入時佈局錯亂
/* 強制使內容塊分列的隱藏列 */
&::before,
&::after {
content: "";
flex-basis: 100%;
width: 0;
order: 2;
}
/* 重新定義內容塊排序優先順序,讓其橫向排序 */
&.three{//三列
&:nth-child(3n+1) { order: 1; }
&:nth-child(3n+2) { order: 2; }
&:nth-child(3n) { order: 3; }
}
&.two{//兩列
&:nth-child(2n+1) { order: 1; }
&:nth-child(2n) { order: 2; }
}
}
js
function getListHeight(){
//獲取當前子項list
let list=document.getElementsByClassName("item")
if(list&&list.length>0){
const heightArr=[0,0,0]
//按順序獲取每列的高度
for(let i=0;i<list.length;i++){
if(i%3===0)heightArr[0]+=list[i].offsetHeight
if(i%3===1)heightArr[1]+=list[i].offsetHeight
if(i%3===2)heightArr[2]+=list[i].offsetHeight
}
//取最大值為父元素設置高度
const maxHeight=Math.max(...heightArr)+50
$(".waterfall").css({height:maxHeight+'px'});
}else{
//沒有子項則重置高度
$(".waterfall").css({height:'auto'});
}
}
以上就是全部解決過程,文中flex佈局方式參考瞭如下文章,感謝分享
https://www.cnblogs.com/xiaoxiaomini/p/17240258.html