两种纯CSS实现瀑布流布局

5,973 阅读3分钟

Multi-columns

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

<template>
 <div class="masonry">
    <div class="item">
        <div class="item__content">
        </div>
    </div>
    <div class="item">
        <div class="item__content">
        </div>
    </div>
    <div class="item">
        <div class="item__content">
        </div>
    </div>
    <div class="item">
        <div class="item__content">
        </div>
    </div>
    <div class="item">
        <div class="item__content">
        </div>
    </div>
    <div class="item">
        <div class="item__content">
        </div>
    </div>
    <div class="item">
        <div class="item__content">
        </div>
    </div>
      <div class="item">
        <div class="item__content">
        </div>
    </div>
      <div class="item">
        <div class="item__content">
        </div>
    </div>
      <div class="item">
        <div class="item__content">
        </div>
    </div>

</div>
</template>

<script>
  export default {
    data() {
      return {
      }
    },
    methods: {
 
    }
  };
</script>

<style scoped>
 .masonry {
     -moz-column-count:5; /* Firefox */
-webkit-column-count:5; 
    column-count: 5;
    column-gap: 5;
    background-color: blue;
}

.item {
    break-inside: avoid;
    box-sizing: border-box;
    padding: 10px;
     background-color:red;
     border: 1px solid #000;
     height: 300px;
     width: 300px;
}

</style>

在.masonry中设置column-count和column-gap,前者用来设置列数,后者设置列间距。 上面控制了列与列之间的效果,但这并不是最关键之处。当初纯CSS实现瀑布流布局中最关键的是堆栈之间的间距,而并非列与列之间的控制(说句实话,列与列之间的控制float之类的就能很好的实现)。找到实现痛楚,那就好办了。或许你会问有什么CSS方法可以解决这个。在CSS中有一个break-inside属性,这个属性也是实现瀑布流布局最关键的属性

其中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
    }
}

Flexbox

Flexbox布局到今天已经是使用非常广泛的,也算是很成熟的一个特性 结构依旧和Multi-columns小节中展示的一样。只是在.masonry容器中使用的CSS不一样:

.masonry {
    display: flex;
    flex-flow: column wrap;
    width: 100%;
    height: 800px;
}

之前在.masonry中是通过column-count来控制列,这里采用flex-flow来控制列,并且允许它换行。这里关键是容器的高度,示例中显式的设置了height属性,当然除了设置px值,还可以设置100vh,让.masonry容器的高度和浏览器视窗高度一样。记住,这里height可以设置成任何高度值(采用任何的单位),但不能不显式的设置,如果没有显式的设置,容器就无法包裹住项目列表。

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

变更后的HTML结构看起来像这样

<template>
 <div class="masonry">
     <div class="column">
        <div class="item">
        <div class="item__content">
        </div>
    </div>
     </div>
    <div class="column">
    <div class="item">
        <div class="item__content">
        </div>
    </div>
    </div>
     <div class="column">
    <div class="item">
        <div class="item__content">
        </div>
    </div>
     </div>
      <div class="column">
    <div class="item">
        <div class="item__content">
        </div>
    </div>
      </div>
       <div class="column">
    <div class="item">
        <div class="item__content">
        </div>
    </div>
       </div>
        <div class="column">
    <div class="item">
        <div class="item__content">
        </div>
    </div>
        </div>
         <div class="column">
    <div class="item">
        <div class="item__content">
        </div>
    </div>
         </div>
          <div class="column">
      <div class="item">
        <div class="item__content">
        </div>
    </div>
          </div>
           <div class="column">
      <div class="item">
        <div class="item__content">
        </div>
    </div>
           </div>
            <div class="column">
      <div class="item">
        <div class="item__content">
        </div>
    </div>
            </div>
</div>
</template>

<script>
export default {
  data() {
    return {};
  },
  methods: {}
};
</script>

<style scoped>
.masonry {
  display: flex;
  flex-direction: row;
  flex-flow: wrap;
}
.column{
   display: flex;
   flex-direction: column;
  width: calc(100%/5);

}
.item {
  break-inside: avoid;
  box-sizing: border-box;
  padding: 10px;
  background-color: red;
  border: 1px solid #000;
  height: 300px;
  width: 300px;
}
</style>

不难发现,在div.item外面包了一层div.column,这个div.column称为列表项目的单独容器。在这个解决方案中,.masonry和.column都通过display:flex属性将其设置为Flex容器,不同的是.masonry设置为行(flex-direction:row),而.column设置为列(flex-direction)

以上内容转至纯CSS实现瀑布流布局