css多列布局 multi-column(瀑布流布局)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了css多列布局 multi-column(瀑布流布局)相关的知识,希望对你有一定的参考价值。

参考技术A column-count :指定元素应该分为的列数

column-fill:指定css如何填充列

column-gap:指定列之间的差距

column-rule:对于设置所有column-rule-*属性的简写属性

column-rule-color:指定列之间的颜色规则

column-rule-style:指定列之间的样式规则

column-rule-width:指定列之间的宽度规则

column-span:指定元素应该跨越多少列

column-width:指定列的宽度

columns缩写属性设置列宽和列数

 break-inside: avoid //防止断裂

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

 博客地址:https://ainyi.com/60

 

纯 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- 

以上是关于css多列布局 multi-column(瀑布流布局)的主要内容,如果未能解决你的问题,请参考以下文章

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

CSS多列布局Multi-column伸缩布局Flexbox网格布局Grid详解

用css3的 clomus 布局 怎么写瀑布流

css 瀑布流布局问题 高手进

应用动态规划和贪心算法高效实现瀑布流布局

前端瀑布流布局如何应用动态规划和贪心算法