首页 > 其他分享 >css+js瀑布流布局实现

css+js瀑布流布局实现

时间:2023-12-27 18:13:57浏览次数:27  
标签:flex pic column picNode js 瀑布 waterfall var css

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

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

标签:flex,pic,column,picNode,js,瀑布,waterfall,var,css
From: https://www.cnblogs.com/pp1211/p/17931045.html

相关文章

  • uni-app和Vue.js有什么区别?
    Hello,大家好,我是咕噜铁蛋!在当今的前端开发领域,uni-app和Vue.js都是非常热门的技术。很多开发者经常在选择时感到困惑。今天铁蛋这篇文章讲和大家探讨这两者的区别,帮助各位在开发路上做出明智的选择。1.uni-app是一个使用Vue.js开发所有前端应用的框架,支持一次编译多端运行。开发者......
  • 原生js和jquery判断单选复选框是否选中
    用jquery判断设置单选复选框时,有时会有些迷糊,今天总结下。<dl><dt>单选框</dt><dd><label><inputtype="radio"name="gender"value="男"/>男</label><label><inputtype="radio"name=......
  • Nextjs SyntaxError: Cannot use import statement outside a module错误
    NextJs报 SyntaxError:Cannotuseimportstatementoutsideamodule第三方依赖不能导入问题 解决方案:1,Next.JS13.1+,可以使用next.config.js中的属性transpilePackagesconstnextConfig={transpilePackages:['the-npm-package'],//第三方的依赖};module.expo......
  • Javascript 原型链 jQuery原型链 js原型链 我感觉我能一直写下去 扶着我>_<
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>原型链闭环</title><scriptsrc="./jquery.js"></script></head><body><divclass=&quo......
  • 黑马pink css7
    定位的作用1:让盒子自由地在某个盒子内移动位置或者固定屏幕中的某个位置,并且可以压住其他盒子。定位=定位模式+边偏移定位模式用于指定一个元素在文档中的定位方式。边偏移则决定了该元素的最终位置。定位模式:position:static、relative、absolute、fixed静态定位static......
  • 贪吃蛇login.js代码
    // pages/login/login.jsPage({  /**   * 页面的初始数据   */  data: {    username:"",    password:"",  },  usernameinput(e){    this.setData({      username:e.detail.value    })  },  passwordinput(e){    this.setDat......
  • js-cookie js-cookie的使用
    js-cookie是什么?js-cookie是一个简单的,轻量级的处理cookies的jsAPI,用来处理cookie相关的插件js-cookie的使用方法一、先下载npminstall--savejs-cookie**二、引入安装好js-cookie插件后,在我们需要处理cookie的地方,简单的通过import引入就可以使用了importCookiesfrom'js-co......
  • nest.js中不同环境的配置读取
    node中不同环境的配置读取在node中最常用的是.env格式的配置文件,他有一个专门的npm包dotenv:我们来创建一个node项目试一下:进入这个目录,安装dotenv:npminstalldotenv然后新建一个.env配置文件:aaa=1bbb=2新建index.js并写入如下内容:require('dotenv').config({p......
  • js的this指向
    在JavaScript中,this是一个特殊的变量,它引用了调用对象。它的指向在不同的上下文中有不同的变化。以下是一些常见的this指向的情况:1.全局上下文:在全局作用域中,this指向全局对象。在浏览器中,这通常是window对象。console.log(this);//window(在浏览器中)2.函数调用:当......
  • JS 日期与毫秒之间互相转换
    时间戳(Unix/Linuxtimestamp)转换工具—在线转换毫秒时间戳工具(toolscat.com) Date()函数:该方法返回日期的毫秒表示(毫秒数精确到毫秒)1.毫秒转日期://2023-3-25格式newDate(1679673600000).toLocaleDateString().replace(/\//g,"-");//2023-03-25格式newDate(1......