1. 程式人生 > >分享:純 css 瀑布流 和 js 瀑布流

分享:純 css 瀑布流 和 js 瀑布流

整體 初始化 onload 其它 一行 edi mar 排列 ref

分享一次純 css 瀑布流 和 js 瀑布流

純 css 寫瀑布流

1.multi-columns 方式:

通過 Multi-columns 相關的屬性 column-countcolumn-gap 配合 break-inside 來實現瀑布流布局。

設置這樣的 html 結構:

 1             <div class="masonry"> 
 2             <div class="item"> 
 3                 <div class="item_content content-lar"> 1
 4                 </
div> 5 </div> 6 <div class="item"> 7 <div class="item_content content-sma"> 2 8 </div> 9 </div> 10 <div class="item"> 11 <div class="item_content content-mid"
> 3 12 </div> 13 </div> 14 <div class="item"> 15 <div class="item_content content-sma"> 4 16 </div> 17 </div> 18 <div class="item"> 19 <div
class="item_content content-mid"> 5 20 </div> 21 </div> 22 <div class="item"> 23 <div class="item_content content-lar"> 6 24 </div> 25 </div> 26 <div class="item"> 27 <div class="item_content content-sma"> 7 28 </div> 29 </div> 30 <div class="item"> 31 <div class="item_content content-lar"> 8 32 </div> 33 </div> 34 <div class="item"> 35 <div class="item_content content-lar"> 9 36 </div> 37 </div> 38 <div class="item"> 39 <div class="item_content content-sma"> 10 40 </div> 41 </div> 42 <div class="item"> 43 <div class="item_content content-mid"> 11 44 </div> 45 </div> 46 <div class="item"> 47 <div class="item_content content-mid"> 12 48 </div> 49 </div> 50 <!-- more items --> 51 </div>

.masonry 是瀑布流容器,裏面放置了列表 item,在 .masonry 中設置 column-count(列數) column-gap(列間距)

item 中設置 break-inside:avoid,這是為了控制文本塊分解成單獨的列,以免項目列表的內容跨列,破壞整體的布局。

在 css 中設置包裹 masonry 和 item 的屬性樣式:

 1             .masonry { 
 2                 -moz-column-count:3; /* Firefox */
 3                 -webkit-column-count:3; /* Safari 和 Chrome */
 4                 column-count:3;
 5                 -moz-column-gap: 2em;
 6                 -webkit-column-gap: 2em;
 7                 column-gap: 2em;
 8                 width: 80%;
 9                 margin:2em auto;
10             }
11             .item { 
12                 padding: 2em;
13                 margin-bottom: 2em;
14                 -moz-page-break-inside: avoid;
15                 -webkit-column-break-inside: avoid;
16                 break-inside: avoid;
17                 background: #f60;
18             }

當然為了布局具有響應式效果,可以借助媒體查詢屬性,在不同屏幕大小的條件下設置瀑布流容器 masonry 的 column-count 來自適應改變列數

 1             @media screen and (max-width: 800px) { 
 2                 .masonry { 
 3                     column-count: 2; // two columns on larger phones 
 4                 } 
 5             } 
 6             @media screen and (max-width: 500px) { 
 7                 .masonry { 
 8                     column-count: 1; // two columns on larger phones 
 9                 } 
10             } 

那麽所產生的效果是:

技術分享圖片

也是根據屏幕大小自適應改變列數

2.flexbox 方式:

html 的結構依舊和上面的 Multi-columns 展示的一樣。只是在 .masonry 容器中使用的 CSS 不一樣:

.masonry 中是通過采用 flex-flow 來控制列,並且允許它換行。

這裏關鍵是容器的高度,我這裏要顯式的設置 height 屬性,當然除了設置 px 值,還可以設置100vh,讓 .masonry 容器的高度和瀏覽器視窗高度一樣。

記住,這裏height可以設置成任何高度值(采用任何的單位),但不能不顯式的設置,如果沒有顯式的設置,容器就無法包裹住項目列表。

1             .masonry { 
2                 height: 800px;
3                 display: flex; 
4                 flex-flow: column wrap;
5                 width: 80%;
6                 margin:2em auto;
7             }

對於 .item,可以不再使用 break-inside:avoid,但其它屬性可以是一樣。

同樣的,響應式設置,使用 Flexbox 實現響應式布局比多列布局 Multi-columns 要來得容易,他天生就具備這方面的能力,只不過我們這裏需要對容器的高度做相關的處理。

前面也提到過了,如果不給 .masonry 容器顯式設置高度是無法包裹項目列表的,那麽這裏響應式設計中就需要在不同的媒體查詢條件下設置不同的高度值:

 1             @media screen and (max-width: 1100px) { 
 2                 .masonry { 
 3                     height: 800px; 
 4                 } 
 5             }
 6             @media screen and (max-width: 800px) {
 7                 .masonry { 
 8                     height: 1100px; 
 9                 } 
10             } 
11             @media screen and (max-width: 600px) { 
12                 .masonry { 
13                     height: 1300px; 
14                 } 
15             } 
16             @media screen and (max-width: 460px) { 
17                 .masonry { 
18                     height: 1600px;
19                 } 
20             } 

那麽所產生的效果是:

技術分享圖片

也是根據屏幕大小自適應改變列數。

看到這裏,我們可以發現,使用純 css 寫瀑布流,每一塊 item 都是從上往下排列,不能做到從左往右排列:

技術分享圖片

這樣子若是動態加載圖片的瀑布流,體驗就會很不好

我們想要的是這樣:

技術分享圖片

這樣做只能通過 js 來寫瀑布流

js 寫瀑布流:

html 結構與上面類似,這裏我用圖片來做示例:

 1         <div class="masonry"> 
 2             <div class="item"> 
 3                 <img class="lazy" src="images/1.jpg" alt="" />
 4             </div> 
 5             <div class="item"> 
 6                 <img class="lazy" src="images/2.jpg" alt="" />
 7             </div>
 8             <div class="item"> 
 9                 <img class="lazy" src="images/3.jpg" alt="" />
10             </div>
11             <div class="item"> 
12                 <img class="lazy" src="images/4.jpg" alt="" />
13             </div>
14             <div class="item"> 
15                 <img class="lazy" src="images/5.jpg" alt="" />
16             </div>
17             <div class="item"> 
18                 <img class="lazy" src="images/6.jpg" alt="" />
19             </div> 
20             <div class="item"> 
21                 <img class="lazy" src="images/7.jpg" alt="" />
22             </div>
23             <div class="item"> 
24                 <img class="lazy" src="images/8.jpg" alt="" />
25             </div>
26             <div class="item"> 
27                 <img class="lazy" src="images/9.jpg" alt="" />
28             </div>
29             <div class="item"> 
30                 <img class="lazy" src="images/10.jpg" alt="" />
31             </div>
32             <div class="item"> 
33                 <img class="lazy" src="images/11.jpg" alt="" />
34             </div>
35             <div class="item"> 
36                 <img class="lazy" src="images/12.jpg" alt="" />
37             </div>
38             <div class="item"> 
39                 <img class="lazy" src="images/13.jpg" alt="" />
40             </div>
41             <div class="item"> 
42                 <img class="lazy" src="images/14.jpg" alt="" />
43             </div>
44             <div class="item"> 
45                 <img class="lazy" src="images/15.jpg" alt="" />
46             </div>
47             <div class="item"> 
48                 <img class="lazy" src="images/16.jpg" alt="" />
49             </div>
50             <div class="item"> 
51                 <img class="lazy" src="images/17.jpg" alt="" />
52             </div>
53             <div class="item"> 
54                 <img class="lazy" src="images/18.jpg" alt="" />
55             </div>
56             <div class="item"> 
57                 <img class="lazy" src="images/19.jpg" alt="" />
58             </div>
59             <div class="item"> 
60                 <img class="lazy" src="images/20.jpg" alt="" />
61             </div>
62             <div class="item"> 
63                 <img class="lazy" src="images/21.jpg" alt="" />
64             </div>
65             <div class="item"> 
66                 <img class="lazy" src="images/22.jpg" alt="" />
67             </div>
68             <div class="item"> 
69                 <img class="lazy" src="images/23.jpg" alt="" />
70             </div>
71             <div class="item"> 
72                 <img class="lazy" src="images/24.jpg" alt="" />
73             </div>
74         </div>

css 內容:

 1             .masonry { 
 2                 width: 100%;
 3                 margin-top: 50px;
 4                 position:relative;
 5             }
 6             .item { 
 7                 z-index: 10;
 8                 transition: 0.25s;
 9                 overflow: hidden;
10                 position: absolute;
11             }
12             .item img{
13                 width: 100%;
14                 height:100%;
15                 transition: 0.25s;
16             }
17             .item:hover img{
18                 z-index: 100;
19                 transition: 0.25s;
20                 overflow: hidden;
21                 animation: bounceIn 0.25s ease-in 2 alternate;
22             }
23             @keyframes bounceIn{
24                 100% {
25                     transform: scale(1.07);
26                 }
27             }

js 瀑布流實現方式:

css 的絕對定位方式:根據每張圖片的位置設置 top 和 left 值:

 1 //瀑布流效果
 2 //這裏有一個坑(已經修復):
 3 //因為是動態加載遠程圖片,在未加載完全無法獲取圖片寬高
 4 //未加載完全就無法設定每一個item(包裹圖片)的top。
 5 
 6 //item的top值:第一行:top為0
 7 //            其他行:必須算出圖片寬度在item寬度的縮小比例,與獲取的圖片高度相乘,從而獲得item的高度
 8 //                   就可以設置每張圖片在瀑布流中每塊item的top值(每一行中最小的item高度,數組查找)
 9 //item的left值:第一行:按照每塊item的寬度值*塊數
10 //             其他行:與自身上面一塊的left值相等
11 function waterFall() {
12     // 1- 確定圖片的寬度 - 滾動條寬度
13     var pageWidth = getClient().width-8;
14     var columns = 3; //3列
15     var itemWidth = parseInt(pageWidth/columns); //得到item的寬度
16     $(".item").width(itemWidth); //設置到item的寬度
17     
18     var arr = [];
19 
20     $(".masonry .item").each(function(i){
21         var height = $(this).find("img").height();
22         var width = $(this).find("img").width();
23         var bi = itemWidth/width; //獲取縮小的比值
24         var boxheight = parseInt(height*bi); //圖片的高度*比值 = item的高度
25 
26         if (i < columns) {
27             // 2- 確定第一行
28             $(this).css({
29                 top:0,
30                 left:(itemWidth) * i
31             });
32             arr.push(boxheight);
33 
34         } else {
35             // 其他行
36             // 3- 找到數組中最小高度  和 它的索引
37             var minHeight = arr[0];
38             var index = 0;
39             for (var j = 0; j < arr.length; j++) {
40                 if (minHeight > arr[j]) {
41                     minHeight = arr[j];
42                     index = j;
43                 }
44             }
45             // 4- 設置下一行的第一個盒子位置
46             // top值就是最小列的高度 
47             $(this).css({
48                 top:arr[index],
49                 left:$(".masonry .item").eq(index).css("left")
50             });
51 
52             // 5- 修改最小列的高度 
53             // 最小列的高度 = 當前自己的高度 + 拼接過來的高度
54             arr[index] = arr[index] + boxheight;
55         }
56     });
57 }
58 
59 
60 //clientWidth 處理兼容性
61 function getClient() {
62     return {
63         width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
64         height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
65     }
66 }
67 
68 
69 
70  // 頁面尺寸改變時實時觸發
71 window.onresize = function() {
72     //重新定義瀑布流
73     waterFall();
74 };
75 
76 
77 
78 //初始化
79 window.onload = function(){
80     
81     //實現瀑布流
82     waterFall();
83 
84 }

效果圖是:

技術分享圖片

這實現了橫向排列的瀑布流效果

分享:純 css 瀑布流 和 js 瀑布流