Native css, js and vue to realize picture waterfall flow

Two ways to realize picture waterfall flow

1.css implementation

<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>pure css Realize picture waterfall flow</title>
    <style>
    .waterfall_container{
      column-count: 3;
      column-gap: 0px;
      width:60%;
      text-align: center;
    }
    .waterfall_item {
      -webkit-column-break-inside: avoid;
      break-inside: avoid;
      counter-increment: item-counter;
      padding-top:5px;
    }
    .waterfall_item img{
      width:90%;
    }
    .waterfall_item p{
      font-size:12px;
      text-align: center;
      margin:8px 0;
    }
    @media screen and (max-width:800px){
    .waterfall_container{
      width:100%;
      column-count: 2;
    }
    }
    </style>
  </head>
  <script src="https://cdn.bootcss.com/vue/2.6.10/vue.common.dev.js"></script>
  <body>
    <div class="waterfall_container" id="app">
      <div class="waterfall_item" v-for="item in items">
        <img :src="'http://23.106.136.165/files/files/yushun/'+item[0]">
        <p>{{item[1]}}</p>
      </div>
    </div>
  </body>
  <script type="text/javascript">
    new Vue({
      el:"#app",
      data:{
        items:[]
      },
      methods:{
        get_result(){
          let that=this;
          setTimeout(function(){
            that.items=[["static/news_images/3536162/20171230113354-3e4ab1e1.jpg", "\u7cbe\u9009\u9762\u79ef72\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u5b9e\u666f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113356-4b0a4dba.jpg", "2018\u7cbe\u900983\u5e73\u65b9\u4e8c\u5c45\u5ba2\u5385\u73b0\u4ee3\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113443-ef9a63d4.jpg", "\u7cbe\u900978\u5e73\u7c73\u4e8c\u5c45\u9910\u5385\u73b0\u4ee3\u88c5\u4fee\u6548\u679c\u56fe"], ["static/news_images/3536162/20171230113400-c075a845.jpg", "\u7cbe\u9009\u9762\u79ef86\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u6b23\u8d4f"], ["static/news_images/3536162/20171230113434-a79ca815.jpg", "2018\u7cbe\u9009\u9762\u79ef70\u5e73\u73b0\u4ee3\u4e8c\u5c45\u9910\u5385\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247"], ["static/news_images/3536162/20171230113351-b9200e9f.jpg", "\u70ed\u95e8\u9762\u79ef78\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u88c5\u4fee\u6b23\u8d4f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113419-66a901f7.jpg", "\u7cbe\u900988\u5e73\u7c73\u4e8c\u5c45\u5367\u5ba4\u73b0\u4ee3\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113405-090f969e.jpg", "201877\u5e73\u7c73\u4e8c\u5c45\u5ba2\u5385\u73b0\u4ee3\u88c5\u4fee\u5b9e\u666f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113446-c61b8e2a.jpg", "\u70ed\u95e877\u5e73\u7c73\u4e8c\u5c45\u8863\u5e3d\u95f4\u73b0\u4ee3\u8bbe\u8ba1\u6548\u679c\u56fe"], ["static/news_images/3536162/20171230113409-67baab71.jpg", "2018\u73b0\u4ee3\u4e8c\u5c45\u53a8\u623f\u88c5\u4fee\u6548\u679c\u56fe\u7247\u5927\u5168"]];
          },1000)
      },
    },
    created(){
      this.get_result();//Simulation request data
    },
    updated(){
    }
    })
  </script>
  </html>

Design sketch:

2.js computing implementation (absolute)

<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>js Realize picture waterfall flow(style:absolute)</title>
  <style>
    .waterfall_container{
      width:50%;
    }
    .waterfall_item {
      padding-top:10px;
      opacity: 0;
      width:33.33%;
    }
    .waterfall_item img{
      width:90%;
    }
    .waterfall_item p{
      font-size:12px;
      text-align: center;
      margin:5px 0;
    }
    *{
      transition: opacity 0.1s;
    }
    @media screen and (max-width:800px){
    .waterfall_container{
      width:100%;
    }
    .waterfall_item{
      width:50%;
    }
    .waterfall_item p{
      font-size:10px;
    }
    }
  </style>
</head>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.common.dev.js"></script>
<body>
  <div id="app">
    <div class="waterfall_container">
      <div class="waterfall_item" v-for="item in items">
        <img :src="'http://23.106.136.165/files/files/yushun/'+item[0]" waterfall>
        <p>{{item[1]}}</p>
      </div>
    </div>
  </div>
</body>
<script type="text/javascript">
  new Vue({
    el:"#app",
    data:{
      items:[]
    },
    methods:{
      get_result(){
        var that=this;
        setTimeout(function(){
          that.items=[["static/news_images/3536162/20171230113354-3e4ab1e1.jpg", "\u7cbe\u9009\u9762\u79ef72\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u5b9e\u666f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113356-4b0a4dba.jpg", "2018\u7cbe\u900983\u5e73\u65b9\u4e8c\u5c45\u5ba2\u5385\u73b0\u4ee3\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113443-ef9a63d4.jpg", "\u7cbe\u900978\u5e73\u7c73\u4e8c\u5c45\u9910\u5385\u73b0\u4ee3\u88c5\u4fee\u6548\u679c\u56fe"], ["static/news_images/3536162/20171230113400-c075a845.jpg", "\u7cbe\u9009\u9762\u79ef86\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u6b23\u8d4f"], ["static/news_images/3536162/20171230113434-a79ca815.jpg", "2018\u7cbe\u9009\u9762\u79ef70\u5e73\u73b0\u4ee3\u4e8c\u5c45\u9910\u5385\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247"], ["static/news_images/3536162/20171230113351-b9200e9f.jpg", "\u70ed\u95e8\u9762\u79ef78\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u88c5\u4fee\u6b23\u8d4f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113419-66a901f7.jpg", "\u7cbe\u900988\u5e73\u7c73\u4e8c\u5c45\u5367\u5ba4\u73b0\u4ee3\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113405-090f969e.jpg", "201877\u5e73\u7c73\u4e8c\u5c45\u5ba2\u5385\u73b0\u4ee3\u88c5\u4fee\u5b9e\u666f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113446-c61b8e2a.jpg", "\u70ed\u95e877\u5e73\u7c73\u4e8c\u5c45\u8863\u5e3d\u95f4\u73b0\u4ee3\u8bbe\u8ba1\u6548\u679c\u56fe"], ["static/news_images/3536162/20171230113409-67baab71.jpg", "2018\u73b0\u4ee3\u4e8c\u5c45\u53a8\u623f\u88c5\u4fee\u6548\u679c\u56fe\u7247\u5927\u5168"]];
          console.log("get_info_finish");
        },1000)
    },
  getMaxHeight(arr){
    return Math.max.apply(null, arr)+"px";
  },
  getMinHeightIndex(arr){
    var minHeight=Math.min.apply(null, arr);
    if (!arr.indexOf){
        Array.prototype.indexOf=function(obj){
        var i=this.length;
            while(i-=1){
                if(this[i]==obj){
                    return i;
                }
            }return -1;
        }
    }
    return arr.indexOf(minHeight);
  },
  waterFall() {
      let imgs = document.querySelectorAll('img[waterfall]');
      let gradparentDIV=imgs[0].parentNode.parentNode;
      gradparentDIV.style.position="relative";
      let gap=0
      let pageWidth = gradparentDIV.offsetWidth;
      let itemWidth = imgs[0].parentNode.offsetWidth;
      let columns = Math.round(pageWidth / (itemWidth + gap));
      let top_Arr = [];
      let left_Arr = [];
      let loaded_count=0;
      var that=this;
      console.log("all_pictrues_count:"+imgs.length);
      for (let i = 0; i < imgs.length; i++) {
        var img=new Image();
        img.src=imgs[i].src;
        img.onload=function(){
          var parentDIV=imgs[i].parentNode;
          parentDIV.style.position="absolute";
          if (loaded_count < columns) {
              parentDIV.style.top = 0;
              parentDIV.style.left = (itemWidth + gap) * loaded_count + 'px';
              top_Arr.push(parentDIV.offsetHeight);
              left_Arr.push(parentDIV.style.left);
          } else {
              var index=that.getMinHeightIndex(top_Arr);
              parentDIV.style.top = top_Arr[index] + gap + 'px';
              parentDIV.style.left = left_Arr[index];
              top_Arr[index] = top_Arr[index] + parentDIV.offsetHeight + gap;
          }
          parentDIV.style.opacity="1";
          gradparentDIV.style.height=that.getMaxHeight(top_Arr);
          loaded_count++;
          // console.log("loaded_count:"+loaded_count);
          // console.log("loaded_index:"+i);
          if(imgs.length==loaded_count){
            console.log("loaded_all_pictrues");
          }
        }
      }
    },
    windowResizeLister(){
      var that=this;
      window.addEventListener("resize",function(){
        that.waterFall();
      })
    }
  },
  created(){
    this.get_result();//Simulation request data
  },
  updated(){    
    this.$nextTick(function () {
      this.windowResizeLister();
      this.waterFall();
    })
  }
  })
</script>
</html>

Design sketch:

Contrast:

  • css is relatively simple, but the effect is not so good.
  • js calculation is complex, but the effect is good.

demo1 address:

https://huxiaofan1223.github.io/htmlDemo/waterFall/css_waterfall.html

demo2 address:

https://huxiaofan1223.github.io/htmlDemo/waterFall/js_waterfall.html

Technically

demo1 is very simple and has nothing to say, because js is not used.
Demo2 = > JS, one of the difficulties is that the pictures are downloaded asynchronously. You need to judge whether the pictures have been downloaded, and then you can open the div to make it have offsetHeight

        for (let i = 0; i < imgs.length; i++) {
        	var img=new Image();
        	img.src=imgs[i].src;
       	    img.onload=function(){
        		do_calculate_and_DOM(); //Perform complex calculations and operate dom
        	}
       	 }

Thank

Several css layouts (document flow, floating, waterfall flow, flex, flexbox) with multiple columns of the same width and height of the artful Gadget:
https://blog.csdn.net/Artful_Dodger/article/details/79761760
Levi's native js realizes waterfall flow effect:
https://segmentfault.com/a/1190000012621936?utm_medium=referral&utm_source=tuicool

Keywords: Vue Javascript github

Added by Domcsore on Wed, 13 Nov 2019 19:03:20 +0200