纯CSS实现瀑布流布局

瀑布流布局有一个专业的英文名称Masonry Layouts。瀑布流布局已经有好多年的历史了,我最早知道这个名词的时候大约是在2012年,当时Pinterest网站的布局就是使用的这种流式布局,简言之像Pinterest网站这样的布局就称之为瀑布流布局,也有人称之为Pinterest 布局。

瀑布流布局其核心是基于一个网格的布局,而且每行包含的项目列表高度是随机的(随着自己内容动态变化高度),同时每个项目列表呈堆栈形式排列,最为关键的是,堆栈之间彼此之间没有多余的间距差存大。还是上张图来看看我们说的瀑布流布局是什么样子。

当初要实现这样的布局都是依赖于JavaScript来实现,所以当时出现过很多实现瀑布流布局的插件。比如MasonryIsotope等都是非常有名的插件。但使用纯CSS来实现,当时还是非常困难的,不管是使用float还是inline-block布局都无法很好的控制列表项目堆栈之间的间距。最终得到的效果就像下面这样:

现在距离2012年已经过去了五个年头,CSS的技术更新也是日新月异,在这几年当中出现了很多新的布局方法,比如多列布局multi-columns、Flexbox布局以及今年浏览器支持有Grid布局。早前在《CSS布局的未来》一文中有对这些布局做过阐述。既然CSS的布局有这么多的变化,那么今天有没有不借助任何JavaScript(纯CSS方案)能否实现瀑布流布局?答案是肯定的,接下来的内容,我们就使用不同的CSS布局方案来实现瀑布流布局。

 

首先最早尝试使用纯CSS方法解决瀑布流布局的是CSS3 的Multi-columns。其最早只是用来用来实现文本多列排列(类似报纸杂志样的文本排列)。但对于前端同学来说,他们都是非常具有创意和创新的,有人尝试通过Multi-columns相关的属性column-countcolumn-gap配合break-inside来实现瀑布流布局。

<div class="masonry"> 
    <div class="item medium"> <div class="item__content"> </div> </div> 
    <div class="item medium"> <div class="item__content"> </div> </div>
    <div class="item small"> <div class="item__content"> </div> </div>
    <div class="item large"> <div class="item__content"> </div> </div> 
    <!-- more items -->
 </div>

其中div.masonry是瀑布流的容器,其里面放置了n个列表div.item。为了节约篇幅,上面代码仅列了两个。结构有了,现在来看CSS。在.masonry中设置column-countcolumn-gap,前者用来设置列数,后者设置列间距:

.masonry { column-count: 5; column-gap: 0; }
.item { 
break-inside: avoid; /*这个属性也是实现瀑布流布局最关键的属性*/
box-sizing: border-box; 
padding: 10px; 
}

.medium{
    height: 10rem;
}
.small{
    height: 8rem;
}
.large{
    height: 12rem;
}

其中break-inside:avoid为了控制文本块分解成单独的列,以免项目列表的内容跨列,破坏整体的布局。当然为了布局具有响应式效果,可以借助媒体查询属性,在不同的条件下使用column-count设置不同的列,比如:

.masonry { column-count: 1; // one column on mobile }
@media (min-width: 400px) { 
 .masonry { column-count: 2; // two columns on larger phones } 
}
@media (min-width: 1200px) { 
 .masonry { column-count: 3; // three columns on...you get it 
} 
}
 <!-- etc. -->

比如下面的这个示例:

<div class="masonry">
  <div class="item">
    <div class="item__content">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--small">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--medium">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--small">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--medium">
    </div>
  </div>
  <div class="item">
    <div class="item__content">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--large">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--medium">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--small">
    </div>
  </div>
  <div class="item">
    <div class="item__content">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--large">
    </div>
  </div>
  <div class="item">
    <div class="item__content">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--small">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--large">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--medium">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--small">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--medium">
    </div>
  </div>
  <div class="item">
    <div class="item__content">
    </div>
  </div>
  <div class="item">
    <div class="item__content item__content--small">
    </div>
  </div>
</div>

 

@charset "UTF-8";
@import url("https://fonts.googleapis.com/css?family=PT+Mono");
body,
html {
  position: relative;
  width: 100%;
  height: 100%;
  background: #4F000B;
  font-family: "PT Mono", monospace;
}

.masonry {
  -webkit-column-count: 1;
          column-count: 1;
  -webkit-column-gap: 0;
          column-gap: 0;
  counter-reset: item-counter;
}
@media screen and (min-width: 400px) {
  .masonry {
    -webkit-column-count: 2;
            column-count: 2;
  }
}
@media screen and (min-width: 600px) {
  .masonry {
    -webkit-column-count: 3;
            column-count: 3;
  }
}
@media screen and (min-width: 800px) {
  .masonry {
    -webkit-column-count: 4;
            column-count: 4;
  }
}
@media screen and (min-width: 1100px) {
  .masonry {
    -webkit-column-count: 5;
            column-count: 5;
  }
}

.item {
  box-sizing: border-box;
  -webkit-column-break-inside: avoid;
          break-inside: avoid;
  padding: 10px;
  counter-increment: item-counter;
}
.item__content {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 220px;
  font-size: 40px;
  color: #360007;
  background: currentColor;
  box-sizing: border-box;
  color: #720026;
}
.item__content:hover {
  background: #9b0034;
}
.item__content:before {
  position: absolute;
  top: 0;
  left: 0;
  font-size: 13px;
  width: 2em;
  height: 2em;
  line-height: 2em;
  text-align: center;
  font-weight: bold;
  background-color: #222;
  content: counter(item-counter);
}
.item__content:after {
  color: #1c0004;
  content: 'ಠ‿ಠ';
}
.item__content--small {
  color: #CE4257;
  height: 100px;
}
.item__content--small:hover {
  background: #d66274;
}
.item__content--small:after {
  content: '♥◡♥';
}
.item__content--medium {
  color: #FFC093;
  height: 175px;
}
.item__content--medium:hover {
  background: #ffd8bc;
}
.item__content--medium:after {
  content: '◔ᴗ◔';
}
.item__content--large {
  color: #FF7F51;
  height: 280px;
}
.item__content--large:hover {
  background: #ff9d7a;
}
.item__content--large:after {
  content: 'ಠ_๏';
}

看到上面示例的效果,这个时候是不是有点成就感了,是不是觉得CSS更神奇了?

Flexbox/Grid也可以实现

Flexbox有两种方案,那咱们先来看

方案1这个解决方案有一个最致命的地方,就是需要显式的给.masonry设置height,特别对于响应式设计来说这个更为不友好。而且当我们的项目列表是动态生成,而且内容不好控制之时,这就更蛋疼了。那么有没有更为友好的方案呢?诞生方案2

方案2只不过在结构上变得冗余一点。

Grid中自动排列的算法对于实现瀑布流布局有很大的帮助。不过对于堆栈(列表项目)高度不能友好的控制。


原文: https://www.w3cplus.com/css/pure-css-create-masonry-layout.html

这篇文章主要介绍了如何使用纯CSS实现瀑布流的布局。文章简单介绍了三种实现方案:Multi-columns、Flexbox和Grid。从上面的示例或者实现手段而言,较友好的是Flexbox的方案。当然,随着CSS Grid特性的完善,使用Grid实现瀑布流布局将会变得更为简单和友好。那让我们拭目以待。当然如果你觉得这些方案都不太好,你可以依旧可以考虑JavaScript的解决方案。如果你有更好的解决方案,也希望能在下面的评论中与我们一起分享。

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WebCsDn_TDCode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值