Flexbox布局实战

发布于 大漠

在最近的一个项目中,我们终于将Flexbox广泛用于页面布局当中。通过这次实战,让我对Flexbox相关知识有了更进一步的了解,也在这方面增涨了不少的知识。接下来,我将分三个部分来解释Flexbox在Web布局中的实战。

  • 主要页面布局(一个JavaScript单页面小应用)
  • 流体网格和折叠盒子(Accordion)
  • “Cards”和“Slabs”产品

序言

这不是一篇有关于Flexbox的科普教程,这里有些关于Flexbox的其他教程。但简而言之,使用display:flex可以快速创建一个flexbox或者flex容器。而它的子元素就变成了flex项目,可以设置flex属性。当然,它们自己也可以变成flex容器。

或许,在使用Flexbox给Web页面进行布局时,还在担心浏览器对其兼容性支持力度。如果你对这方面顾虑较深的话,可以通过caniuse.com来查阅。

如果你希望Flexbox在更多的浏览器上都能有一个较好的渲染或呈现方式,需要添加一些浏览器的私有前缀。可以使用Autoprefixer插件来帮助你处理这些琐碎的事情。

主页面布局

这是一个JavaScript写的单页面应用,页面主要包括了标题栏、页脚、canvas展示区域和调整窗口大小的列表选择项。如下图所示:

主页面布局

把所有元素都放置在一个.wrapper容器内,并且通过position:fixed将其大小设置和视窗大小一样。接下来使用display:flex.wrapper变成flex容器,另外使用flex-direction:column让flex项目(.wrapper的子元素)纵向排列。

详细样式用下图向大家展示,将会变得更好理解:

主页面布局

.body-wrapper设置flex:1。这样使用的主要目的是将其可以根据容器可用空间自动拉伸填补。简而言之,就是让.body-wrapper的高度变成(100vh - 标题栏高度 - 页脚高度)。其实flex:1flex: 1 1 0的简写方式,也就是flex-grow:1(拉伸)、flex-shrink:1(缩小)、flex-basis:0(没有最小高度min-height)。

.header-wrapper.body-wrapper.footer-wrapper.wrapper的flex项目,其实它们也是一个flex容器。而且它们的子元素也是一个flex项目,并且是水平方向排列,那是因为flex-direction:row(也就是flex-direction的默认值)。另外通过align-items:center来保证不管是页头或页脚的高度是多少,都让其子元素垂直居中(类似table中的vertical-align:middle)。

.header-wrapper.body-wrapper中都有一个元素设置了flex:1,主要是让其能自动填充可用空间。而且在.footer-wrapper中需要给每个flex项目设置flex: 1 1 auto(改变flex-basis的值为auto),这样让.footer-wrapper的flex项目平分页脚区域宽度。

注意,不管左边的面板.pane-wrapper设置多少值,.canvas-wrapper都会自适应。而且如果需要,还可以通过order属性改变它们的排列顺序。

.pane-wrapper.canvas-wrapper都设置为flex容器,并且能过flex-direction:column将其flex项目纵向排列(它们都有一个标题区和主体区)。使用flex-direction:row.pane-body设置为flex容器。严格来说在flexbox中是不必要的,因为.canvas-wrapper.pane-body是最终的设置,而且.pane-content.canvas都设置了position:absolute。它们不会影响外容器的高度计算,它们每个都可以滚动。如果.pane-content.canvas是flex项目的话,看上去不是这样的结果。

**在没有Flexbox布局模块之前,我们如何实现类似这样的布局呢?**在前一个项目中有一个非常相似的布局,我们给每个区域都使用position:fixed。这种布局方式对于旧浏览器具有较好的支持。但成本是在CSS要通过像.with-header.with-footer.with-titlebar.with-sidebar等类名对各个位置进行计算,而且位置改变时还需要通过JavaScript进行动态计算。更为麻烦的是,你改变一个值,其它的容器也要相应的改变。

同时要让行内元素垂直对齐,还需要使用一些让人讨厌的Hacks。

如果你对垂直对齐相关的知识感兴趣,你可以点击这里阅读。

产品列表和摘要盒子

Flexbox很适合流体产品列表(A区)以及像折叠卡片(Accordion)摘要盒子(B区),如下图所示:

产品列表和摘要盒子

在这里面还有一个自适应的弹出窗(Modal),而且能随着窗口的widthheight缩放按比例调整Modal大小。(使用了Bootstrap的Modal模板,.modal.modal-content.modal-body都设置了百分比高度)。首先设置.col-wrapper为flex容器,并且使用flex-direction:row让flex项目水平排列。另外设置align-items:stretch让每一个flex项目具有相同的高(每列等高)。由于它们都在已高度的容器内,使用height: 100%可以拉伸到全屏高度。.col-content设置flex:1,可以让其自动填充水平可用空间,并且通过flex: 0 0 <width>.col-facets.col-summary设置宽度百分比。.col-facets.col-content设置了overflow:auto,因此它们有滚动条。

产品列表和摘要盒子

很多地方对于产品的布局都会采用网格形式,不管是“card”还是“slab”的形式(下一节将详细介绍这部分)。这些都是弹性布局,其宽度都会自适应容器的宽度。但也会使用媒体查询来控制列数,允许在任何屏幕上有一种较好的布局效果。

.product-grid是一个flex容器。设置了flex-wrap:wrap允许flex项目可以换行,同时设置align-items:stretch让同行的flex项目有相同的高度。.product是flex项目,每个Products有一个1%margin-leftmargin-right。相当于两个flex项目之间有2%的间距(容器也有一个padding-leftpadding-right1%)。.product的宽度使用flex-basis设置一个百分比,其值相当于:flex: 0 0 (100 / 3) - 2%(三列,每两列之间的间距是2%)。你也可以看上图中有关于媒体查询部分中相应的调整。

使用Flexbox是制作流体网格最好的方式?这个方法看起来很简单,完全依靠给flex-basis设置一个百分比值,而不是flex-grow或者flex-shrink。似乎没有比float-based更好的方法,尽管我们具有一样高度的盒子的优势。主要原因是项目最后一行对齐到网格。如果最后一行没有完全填满,大多数flexbox网格会填充空间,允许项目的宽度变长,或者增加它们之间的间距。这些在我们的案例中都是可接受的结果。这里有一个示例,感兴趣的可以看看。

让摘要区域能填满垂直的空间是有一定的挑战性的。.summary-content拉伸填充可用空间,当空间填满后滚动条也将出现。.summary-box需要设置height100%(其容器也指定了高度)和.summary-content需要设置flex-grow: 1flex-shrink:1,让flex项目可以根据需要扩展或缩小。overflow:auto让容器滚动条在需要的出现。

没有Flexbox,要轻松实现这样的效果是有点不可能,因为无法预知盒子的高度。

产品列表和摘要盒子

Cards和Slabs

产品列表形式要么是大的Cards或者是紧凑形的Slabs。在每种情况下Flexbox都非常有帮助。

Cards和Slabs

.product-card有一个元素.product-desc让其自动填充垂直方向的可用空间。如果指定一个max-height.product-desc会被截断。如果我们想把图片放到标题上面,在Flexbox布局上除了改变HTML结构之外,还可以通过order来改变他们的顺序。

对于.product-slab我们需要内容两端对齐,在没有Flexbox,需要采用float和清除浮动,但无法根据内容数量分配水平空间,这对于前端来说是一种痛苦。那么有了Flexbox,这一切变得都轻松。

flex-direction:row让内容水平排列。通过justify-content:space-between让标题和内容实现两端对齐。在.product-title设置flex-grow:1确保水平空间内能让其居左对齐。

总结

这个项目是一个宝贵的学习经验。Flexbox可能让你得到出人意料的结果,大家应该以最好的方式和认真的学习它。尽管大多数项目中还不能依靠Flexbox来做布局,主要是考虑浏览器的兼容性。但仍然有很多例子证明了,可以对Flexbox做一些降级处理。比如@Zoe Gillenwater整得的相关教程和资料。时到今日,使用Flexbox的场景也越来越多,在将来使用Flexbox场景将会更多。

为了让这篇文章篇幅不至于过长,我试图尽可能保持简洁,如果文章中有解释不清楚的或者有些事情不对的,希望帮忙指出。如果想对Flexbox做深入的学习和研究,建议点击这里了解更多的相关内容。

本文根据@Francois Jordaan的《Going all-in on Flexbox》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:https://www.isotoma.com/blog/2016/09/07/going-all-in-on-flexbox/

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:https://www.fedev.cn/css3/going-all-in-on-flexbox.htmljordan retro 11 mens china