css+js瀑布流布局实现

  • css+js瀑布流布局实现已关闭评论
  • 77 次浏览
  • A+
所属分类:Web前端
摘要

最开始使用js实现,将子元素进行绝对定位,根据宽高及顺序判断定位的top与left。


记录一个瀑布流布局问题的解决过程

最开始使用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