瀑布流布局Flex

Flexbox

Flexbox布局到今天已经是使用非常广泛的,也算是很成熟的一个特性。那接下来我们就看Flexbox怎么实现瀑布流布局。如果你从未接触过Flexbox相关的属性,那建议你点击这里阅读。如果你觉得这里信息量过于太多,那强列建议你阅读下面几篇文章,阅读完之后你对Flexbox相关属性会有一个彻底的了解:

上面这几篇文章告诉了你有关于Flexbox的一切:

image

接下来回到我们今天的正题当中,使用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可以设置成任何高度值(采用任何的单位),但不能不显式的设置,如果没有显式的设置,容器就无法包裹住项目列表。

使用Flexbox布局,对于.item可以不再使用break-inside:avoid,但其它属性可以是一样。同样的,响应式设置,使用Flexbox实现响应式布局比多列布局要来得容易,他天生就具备这方面的能力,只不过我们这里需要对容器的高度做相关的处理。前面也提到过了,如果不给.masonry容器显式设置高度是无法包裹项目列表的,那么这里响应式设计中就需要在不同的媒体查询条件下设置不同的高度值:

.masonry {
    height: auto;
}

@media screen and (min-width: 400px) {
    .masonry {
        height: 1600px;
    }
}

@media screen and (min-width: 600px) {
    .masonry {
        height: 1300px;
    }
}

@media screen and (min-width: 800px) {
    .masonry {
        height: 1100px;
    }
}

@media screen and (min-width: 1100px) {
    .masonry {
        height: 800px;
    }
}

同样来看一个示例效果:

<iframe id="jmEzEm" src="https://codepen.io/airen/embed/jmEzEm?height=400&theme-id=0&slug-hash=jmEzEm&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 940px; overflow: hidden;"></iframe>

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

前面说到过Flexbox有两种方案,那咱们先来看方案二,再来回答这个问题。

单独的列容器

这个方案,我们需要对我们的HTML结构做一个变更。变更后的HTML结构看起来像这样:

<div class="masonry">
    <div class="column">
        <div class="item">
        <div class="item__content">
        </div>
        </div>
        <!-- more items -->
    </div>
    <div class="column">
        <div class="item">
        <div class="item__content">
        </div>
        </div>
        <!-- more items -->
    </div>
    <div class="column">
        <div class="item">
        <div class="item__content">
        </div>
        </div>
        <!-- more items -->
    </div>
</div>

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

.masonry {
    display: flex;
    flex-direction: row;
}

.column {
    display: flex;
    flex-direction: column;
    width: calc(100%/3);
}

这里有一个需要注意,在.column咱们通过calc()方法来控制每个列的宽度,如果你希望是三列,那么可以设置width: calc(100% / 3);实际中根据自己的设计来设置width

.masonry {
    display: flex;
    flex-direction: row;
}

.column {
    display: flex;
    flex-direction: column;
    width: calc(100%/3);
}

这种方案对应的响应式设计,需要在不同的媒体查询下修改width值,比如:

.masonry {
    display: flex;
    flex-direction: column;
}

@media only screen and (min-width: 500px) {
    .masonry {
        flex-direction: row;
    }
}

.column {
    display: flex;
    flex-flow: column wrap;
    width: 100%;
}

@media only screen and (min-width: 500px) {
    .column {
        width: calc(100%/5);
    }
}

效果如下:

<iframe id="PpEPWG" src="https://codepen.io/airen/embed/PpEPWG?height=400&theme-id=0&slug-hash=PpEPWG&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 940px; overflow: hidden;"></iframe>

从实战结果已经告诉你答案了。只不过在结构上变得冗余一点。
以上摘自大漠w3cplus

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 10,380评论 1 88
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    love2013阅读 855评论 0 10
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    wzhiq896阅读 772评论 0 2
  • 前言 在上篇文章里面谈了Weex在iOS客户端工作的基本流程。这篇文章将会详细的分析Weex是如何高性能的布局原生...
    一缕殇流化隐半边冰霜阅读 15,862评论 48 122
  • H5移动端知识点总结 阅读目录 移动开发基本知识点 calc基本用法 box-sizing的理解及使用 理解dis...
    Mx勇阅读 2,301评论 0 25