瀑布流,木桶,等高,圣杯,雙飛翼布局

1.瀑布流布局

  • 思路:
    要求:當(dāng)圖片寬度相同,高度不同時;如何做一面圖片墻;每次圖片加載到每列最低的位置;
    1.圖片的容器要相對定位,圖片要相對容器絕對定位;
    2.首先要求出當(dāng)瀏覽器打開時或者改變大小時,瀏覽器的窗口能放入幾張圖片;即形成幾列;
    3.創(chuàng)建一個空數(shù)組來存放每列的高度值;
    4.當(dāng)有圖片加載時根據(jù)數(shù)組里存放的高度大小;把圖片放入高度最小的列;
    5.當(dāng)放入后更改放入后的高度;這樣每次都可以把圖片放入高度最低的列里形成好看的圖片墻了。

  • 重點:

 .content{
            position:relative;
        }
 .item{
            position: absolute;
           transition:all 1s; /*漸變效果*/
         }
 function waterFull(){
                var nodeWidth =$('.item').width();//元素寬度
                var num  =parseInt($('.content').width()/nodeWidth)//一排放多少個(取整)
                var itemArr = [];//存放每列的高度;
                for(var i=0; i<num;i++){//初始化
                itemArr[i]=0;//目前每列高度為0;
            }
            
            $('.item').each(function(){//循環(huán)所有圖片
                var minValue = Math.min.apply(null,itemArr) //獲取數(shù)組最小值(第一次就是數(shù)組的第一項0;)
                var minIndex = itemArr.indexOf(minValue)//獲取最小值的下標(biāo);

                $(this).css({//通過改變top left ;放入圖片的位置;
                    top:itemArr[minIndex],
                    left:$(this).outerWidth(true)*minIndex

                })
                itemArr[minIndex] += $(this).outerHeight(true);//更改添加后列的高度
            })

     }  
  • 看下效果:
20170404_183059.gif
  • 優(yōu)化:

1.在改變窗口大小時重新加載圖片位置
2.當(dāng)滾動時繼續(xù)的加載圖片;(寫一個判斷是否加載的函數(shù)checkScroll)
3.當(dāng)滾動時發(fā)送ajax性后端要數(shù)據(jù)加載圖片;(我這里是自己給的數(shù)據(jù)json模擬)
4.優(yōu)化代碼放入立即執(zhí)行函數(shù);

var WaterFull=(function(){
      function init(){
             waterFull()
            $(window).resize(function(){//改變窗口大小
              waterFull()
           })
            $(window).on('scroll',Scroll)//當(dāng)窗口滾動時Mocks數(shù)據(jù);
           

         }
    function waterFull(){
                var nodeWidth =$('.item').width();//元素寬度
                var num  =parseInt($('.content').width()/nodeWidth)//一排放多少個(取整)
                var itemArr = [];//存放每列的高度;
                for(var i=0; i<num;i++){//初始化
                itemArr[i]=0;//目前每列高度為0;
            }
            
            $('.item').each(function(){//循環(huán)所有圖片
                var minValue = Math.min.apply(null,itemArr) //獲取數(shù)組最小值(第一次就是數(shù)組的第一項0;)
                var minIndex = itemArr.indexOf(minValue)//獲取最小值的下標(biāo);

                $(this).css({//通過改變top left ;放入圖片的位置;
                    top:itemArr[minIndex],
                    left:$(this).outerWidth(true)*minIndex

                })
                itemArr[minIndex] += $(this).outerHeight(true);//更改添加后列的高度
            })

     }  
     function Scroll(){
          var dataInt = {
            'data':[{'src':'1.png'},{'src':'2.png'},{'src':'3.png'},{'src':'4.png'},{'src':'5.png'},{'src':'6.png'},{'src':'7.png'},
            {'src':'8.png'},{'src':'9.png'},{'src':'10.png'},{'src':'11.png'},{'src':'12.png'},{'src':'13.png'},{'src':'14.png'}]
            }
          var isArrive= false;//防止多次滾動重復(fù)數(shù)據(jù)
              if(checkScroll() && !isArrive){
                  var oParent = document.getElementsByClassName('content')[0];
                  for(var i =0;i<dataInt.data.length;i++){
                      isArrive=true;
                      var oDiv =document.createElement('div');//添加元素節(jié)點
                      oDiv.className ='item';
                      oDiv.innerHTML ='![](./img/'+dataInt.data[i].src+')'
                      oParent.appendChild(oDiv);                    
                  }
                  isArrive = false;
                  waterFull()
              }
          } 

     function checkScroll(){
             var   oParent = document.getElementsByClassName('content')[0];
             var   aDiv =oParent.getElementsByClassName('item');
             var   lastPinH=aDiv[aDiv.length-1].offsetTop+Math.floor(aDiv[aDiv.length-1].offsetHeight/2); 
             //創(chuàng)建【觸發(fā)添加塊框函數(shù)waterfall()】的高度:最后一個塊框的距離網(wǎng)頁頂部+自身高的一半(實現(xiàn)未滾到底就開始加載)
             var   scrollTop=$(window).scrollTop();//滾動高度
             var   winndowHeight=$(window).height(); //頁面高度
             return   (lastPinH<scrollTop+winndowHeight)? true : false ; //到達(dá)指定高度后 返回true,觸發(fā)waterfall()函數(shù)
        }
     return {
              init:init
          }
     })()
     
     WaterFull.init();

  • 原生js代碼
  function waterFull(){
             var Oparent = document.getElementById('main');
             var aPin =Oparent.getElementsByClassName('pin')//獲取存儲塊pin的數(shù)組;
             var num =Math.floor(document.documentElement.clientWidth/aPin[0].offsetWidth)//獲取窗口每行能容納的個數(shù)
            
             var pinHArr=[];//用于存儲 每列中的所有塊框相加的高度
             for(var i =0 ; i<num;i++){
                 pinHArr[i]=0;
             }
             for(var i =0 ; i<aPin.length;i++){
                
                     //獲取PinHArr的最小值;
                     var minValue =Math.min.apply(null,pinHArr);
                     //獲取pinHArr最小值得索引;
                     var minIndex = pinHArr.indexOf(minValue);
                       
                         aPin[i].style.top=minValue+'px';//用定位改變其top值
                         aPin[i].style.left=aPin[minIndex].offsetWidth*minIndex+'px';//用定位改變其left值
                        
                     
                     pinHArr[minIndex] += aPin[i].offsetHeight;//更改添加后列的高度
                 }
             }
  • css瀑布流效果:
20170404_221332.gif
  • 關(guān)于css瀑布流:
    方法有許多種,優(yōu)缺點都有,但是本人建議用js或者jquery;因為畢竟是要向后端mock數(shù)據(jù)所以css布局不建議使用;就給出css3方法其中一種代碼
     <style>
        *{padding:0;margin:0;}
        .clearfix:after,
        .clearfix:before {
        content: " ";
        display: table;
        }
        .clearfix:after {
        clear: both;
        }
        .main {
        position: relative;
        -webkit-column-width: 222px;
        -moz-column-width: 222px;
        /*column-width 屬性規(guī)定列的寬度。*/
        -webkit-column-gap: 5px;
        /*column-gap 屬性規(guī)定列之間的間隔。*/
        -moz-column-gap: 5px;
        }
        .box {
        float: left;
        padding: 15px 0 0 15px;
        transition: all 1s;
        }
        .box .pic {
            width: 200px;
            height: auto;
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 0 5px #cccccc;     
        }            
       .box .pic img {
               display: block;
               width: 100%;
        }
  • css3瀑布流布局:
    我們將要用到的是CSS3新加的column屬性,通過指定容器的列個數(shù)column-count,列間距column-gap,列中間的邊框(間隔邊線)column-rule,列寬度column-width實現(xiàn)。

    優(yōu)點:
    1. 直接用CSS定義,方便快捷,是最好不過了;
    2. 擴(kuò)展方便。

    缺點:
    1. 目前仍有部分瀏覽器不支持CSS3;
    2.CSS3這種方式的數(shù)據(jù)排列是從上到下排列到一定高度后,再把剩余元素依次添加到下一列;

2.木桶布局

  • 思路:

1.當(dāng)圖片加載進(jìn)來時,初始化new的image對象,給圖片定一個高度;獲取等比例下的寬度;
2.把圖片的寬高放入一個空數(shù)組,通過循環(huán)數(shù)組獲取圖片的總寬度;
3.拿獲取的總寬度跟容器寬度相比較,如果總寬度大于容器寬度,那就拿出最后一個圖片的寬度,直到總寬度小于容器的寬度。然后拉伸容器里的圖片讓,圖片填充這個容器的寬度(獲取容器里現(xiàn)在的最后高度)
4.再把數(shù)組清空,放入剛才被拿出的最后放不下那一項(重置數(shù)組總寬度)
5.寫一個函數(shù)渲染每排圖片(把新高度傳入進(jìn)去)。

  • 難點
1.當(dāng)圖片加載進(jìn)來時,初始化new的image對象,給圖片定一個高度;獲取等比例下的寬度;
loadImg:function(){//構(gòu)建url就是一個接口;也可以是ajax;
                  var _this = this //保存作用于的this
                  var imgUrls = this.getImgUrls(40);//如果是ajax是不可能根據(jù)圖片地址獲取他的寬高的

                 $.each(imgUrls,function(idx,url){//所以循環(huán)這個數(shù)組,
                      var  img = new Image();//創(chuàng)建一個圖片對象;
                      img.src =url;
                      img.onload =function(){                  
                          var imgInfo ={
                              target:$(img),//哪一張圖片
                              width:200*(img.width/img.height),//  x/200=img.width/img.height
                              height:200//高度設(shè)為200;

                          }
                          _this.render(imgInfo);
                      }
                  })

               },




2.把圖片的寬高放入一個空數(shù)組,通過循環(huán)數(shù)組獲取圖片的總寬度;
  render: function(imgInfo){
     
     
      var clientWidth = this.$ct.width();
      var rowWidth = 0;
      var newRowHeight = 0;
      var lastImgInfo = imgInfo;

      this.rowList.push(imgInfo);
      for(var i=0; i< this.rowList.length; i++){
         rowWidth = rowWidth + this.rowList[i].width;
      }


3.那獲取的總寬度跟容器寬度相比較,如果總寬度大于容器寬度,那就拿出最后一個圖片的寬度,直到總寬度小于容器的寬度。然后拉伸容器里的圖片讓,圖片填充這個容器的寬度(獲取容器里現(xiàn)在的最后高度)

 if(rowWidth > clientWidth){
        this.rowList.pop();
        rowWidth = rowWidth-lastImgInfo.width//目前每行的寬度;
        newRowHeight = clientWidth*200/rowWidth;
        //   rowWidth/200   ==  clientWidth/ X

      
      

4.再把數(shù)組清空,放入剛才被拿出的最后放不下那一項(重置數(shù)組總寬度)
         this.rowList = [];
        this.rowList.push(imgInfo);
        this.layout(newRowHeight);

5.寫一個函數(shù)渲染每排圖片(把新高度傳入進(jìn)去)
 layout: function(newRowHeight){
      console.log('createRow');
      var $rowCt = $('<div class="img-row"></div>');
      $.each(this.rowList, function(idx, imgInfo){
        var $imgCt = $('<div class="img-box"></div>'),
            $img = $(imgInfo.target);
            $img.height(newRowHeight);
            $imgCt.append($img);
            $rowCt.append($imgCt);
      });
      this.$ct.append($rowCt);

  • 效果:
20170404_222754.gif

3.等高布局

  • 思路:等高布局有幾種不同的方法如定位,但目前為止我認(rèn)為瀏覽器兼容最好最簡便的應(yīng)該是padding補(bǔ)償法。首先把列的padding-bottom設(shè)為一個足夠大的值,再把列的margin-bottom設(shè)一個與前面的padding-bottom的正值相抵消的負(fù)值,父容器設(shè)置超出隱藏,這樣子父容器的高度就還是它里面的列沒有設(shè)定padding-bottom時的高度,當(dāng)它里面的任一列高度增加了,則父容器的高度被撐到它里面最高那列的高度,其他比這列矮的列則會用它們的padding-bottom來補(bǔ)償這部分高度差。因為背景是可以用在padding占用的空間里的,而且邊框也是跟隨padding變化的,所以就成功的完成了一個障眼法。

  • 重點:

.wrap{         
            overflow: hidden;//父容器設(shè)置超出隱藏,這樣子父容器的高度就還是它里面的列沒有設(shè)定padding-bottom時的高度
        }
   .left{
            float: left;
            padding-bottom: 10000px;
            margin-bottom: -10000px;
        }
        .right{
            float: right;
            padding-bottom: 10000px;
            margin-bottom: -10000px;                          
        }
  • 看下效果:
20170404_165914.gif
  • 代碼
<style>
        .wrap{
            width:100%;
            background:#ccc;
            overflow: hidden;
            min-width: 600px;
           
        }
        .left{
            width:300px;
            float: left;
            padding-bottom: 10000px;
            margin-bottom: -10000px;
            background: red;
            text-align: center;
            border: 1px saddlebrown solid;
        }
        .right{
            width:300px;
            float: right;
            padding-bottom: 10000px;
            margin-bottom: -10000px;
            background:green;
            text-align: center;
            border: 1px saddlebrown solid;
            
            
        }
        h2{
            padding: 10px;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="left">
           ![](./img/1.png)
           
        </div>
        <div class="right">
           ![](./img/2.png)
        </div>
    </div>
   <button class="btn1">左側(cè)欄增加高度</button>
   <button class="btn2">右側(cè)欄增加高度</button>
    <script src="jquery-3.2.0.min.js"></script>
    <script>
          $('.btn1').on('click',function(){
              $('.left').append('![](./img/1.png)')
          })
          $('.btn2').on('click',function(){
              $('.right').append('![](./img/2.png)')
          })
    </script>
</body>

4. 圣杯布局

  • 思路:
    圣杯布局解決的問題是兩邊頂寬,中間自適應(yīng)的三欄布局,中間欄要在放在文檔流前面以優(yōu)先渲染。圣杯布局的三欄全部float浮動,但左右兩欄加上負(fù)margin讓其跟中間欄div并排,以形成三欄布局。解決”中間欄div內(nèi)容不被遮擋“問題的思路:圣杯布局,為了中間div內(nèi)容不被遮擋,將中間div設(shè)置了左右padding-left和padding-right后,將左右兩個div用相對布局position: relative并分別配合right和left屬性,以便左右兩欄div移動后不遮擋中間div。

  • 重點:

        div{
             float:left;
         }
    .wrap
    {
        padding-right: 100px;//空出左右位置給左右兩欄;
        padding-left:100px
    }
    .left
    {
        margin-left: -100%;//左邊欄與中間攔并排;
        position: relative;
        left: -100px;//左邊的div寬度大?。?    }
    .right
    {
        margin-left: -100px;//右邊欄與中間攔并排;大小為右邊欄寬度;
        position: relative;
        left: 100px;//左邊的div寬度大??;
    }
  • 看下效果:
20170404_172951.gif
  • 代碼
 <style>
        .wrap{
            border: 1px saddlebrown solid;
            padding-left:100px;
            padding-right: 100px;
            min-width: 600px;
        }
        .clear:after{
            content:'';
            display: block;
            clear:both;
        }
        .main{
            width:100%;
            height: 200px;
            float:left;
            background:red;
        }
        .left{
            float: left;
            width:100px;
            height: 100px;
            background:green;
            margin-left: -100%;
            position: relative;
            left: -100px;

        }
       .right
               {
        float: left;
        width: 100px;
        height: 100px;
        background: pink;
        margin-left: -100px;
        position: relative;
        left: 100px;
        

    }
    </style>
</head>
<body>
     <div class="wrap clear">
        <div class="main"></div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>

5.雙飛翼布局:

  • 思路:
    圣杯布局和雙飛翼布局解決的問題是一樣的,就是兩邊頂寬,中間自適應(yīng)的三欄布局,中間欄要在放在文檔流前面以優(yōu)先渲染。圣杯布局和雙飛翼布局解決問題的方案在前一半是相同的,也就是三欄全部float浮動,但左右兩欄加上負(fù)margin讓其跟中間欄div并排,以形成三欄布局。不同在于解決”中間欄div內(nèi)容不被遮擋“問題的思路不一樣;雙飛翼布局:為了中間div內(nèi)容不被遮擋,直接在中間div內(nèi)部創(chuàng)建子div用于放置內(nèi)容,在該子div里用margin-left和margin-right為左右兩欄div留出位置。

  • 重點:

       .main
       {
        width: 100%;
        float: left;
       }
       .main .mainer//在中間div內(nèi)部創(chuàng)建子div用于放置內(nèi)容,在該子div里用margin-left和margin-right為左右兩欄div留出位置
    {
        margin-left: 120px;
        margin-right: 120px;
    }
       .left
        {
            float: left;
            margin-left: -100%; //左邊欄與中間攔并排;
        }
        .right
        { 
            float: left;
            margin-left: -100px; //右邊欄與中間攔并排
        }
  • 看下效果:
20170404_174837.gif
  • 代碼:
 .wrap
        {
            border: 1px saddlebrown solid;
            min-width: 600px;
        }
        .clear:after
       {
        content: "";
        display: block;
        clear: both;
       }
       .main
       {
        width: 100%;
        height: 200px;      
        float: left;
     

       }
       .main .mainer
    {
        background: black;
        height: 200px;
        margin-left: 120px;
        margin-right: 120px;

    }
       .left
        {
            width:100px;
            height: 100px;
            background:green;
            float: left;
            margin-left: -100%;
            
        }
        .right
        {
            width: 100px;
            height: 100px;
            background: pink;
            float: left;
            margin-left: -100px;
            
        }

    </style>
</head>
<body>
    <div class="wrap clear">
        <div class="main">
            <div class="mainer"></div>
        </div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>
  • 圣杯雙飛翼的區(qū)別:

圣杯布局和雙飛翼布局解決的問題是一樣的,就是兩邊頂寬,中間自適應(yīng)的三欄布局,中間欄要在放在文檔流前面以優(yōu)先渲染。圣杯布局和雙飛翼布局解決問題的方案在前一半是相同的,也就是三欄全部float浮動,但左右兩欄加上負(fù)margin讓其跟中間欄div并排,以形成三欄布局。不同在于解決”中間欄div內(nèi)容不被遮擋“問題的思路不一樣:圣杯布局,為了中間div內(nèi)容不被遮擋,將中間div設(shè)置了左右padding-left和padding-right后,將左右兩個div用相對布局position: relative并分別配合right和left屬性,以便左右兩欄div移動后不遮擋中間div。雙飛翼布局,為了中間div內(nèi)容不被遮擋,直接在中間div內(nèi)部創(chuàng)建子div用于放置內(nèi)容,在該子div里用margin-left和margin-right為左右兩欄div留出位置。

6. Flex布局:

Flex布局也是很常用的布局方法可以點擊鏈接去了解下Flex布局方法用法.
Flex布局

7.最后看下jquery實戰(zhàn)-無限加載-jsonp-瀑布流

20170405_222202.gif

瀑布流
木桶
等高
圣杯
雙飛翼

jquery實戰(zhàn)-無限加載-jsonp-瀑布流

希望對給位朋友有所幫助~~~
版權(quán)歸饑人谷__楠柒所有,如要轉(zhuǎn)載請請注明出處~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 14,118評論 1 92
  • 前言 溫馨提示:本文較長,圖片較多,本來是想寫一篇 CSS 布局方式的,但是奈何 CSS 布局方式種類太多并且實現(xiàn)...
    sunshine小小倩閱讀 3,266評論 0 59
  • 三欄式布局 涉及浮動和清除浮動,主要講解“圣杯”和“雙飛翼”兩種解決方法。這兩種方法實現(xiàn)的都是三欄布局,兩邊的盒子...
    紫電倚青霜閱讀 2,411評論 0 6
  • 代碼1 代碼2 代碼3 代碼4-float版 代碼4-float簡化版 代碼4-flex版 代碼5 圣杯布局 雙飛...
    _Dot912閱讀 663評論 0 0
  • 2016-7-7 晴 有個事我朋友一直不信,但我想讓他信,不知道各位看官看完是否相信?! 我一直都挺“正經(jīng)”的……...
    實干作品閱讀 1,054評論 0 1

友情鏈接更多精彩內(nèi)容