我们就来谈谈Flexbox布局

 In 网页重构 on 2016-03-23 16:48:35 by 小刀

     Flexbox Layout(Flexible Box)模块,W3C官方称为CSS弹性盒子布局,是在CSS3中定义的一种新的布局模式。Flexbox可以控制在容器内的子元素的对齐方式、排列方式以及排序顺序,即使其子元素的尺寸是未知或者动态的情况下。弹性容器的主要特点就是能够调整其子元素的宽度或者高度以使其能在不同分辨率的屏幕下能用最好的方式去填充可用空间。

     Flex布局的主要思想是让容器能使其子元素的宽高(或其他属性)能够以最好的方式去填充可用空间(主要是去适应不同的设备跟分辨率)。一个Flex弹性盒子能让子元素填充可用空间或者为了阻止子元素超出区域而进行收缩。

     Flexbox布局常用于小的应用程序组件之中,而CSS Grid布局模块将应用于大规模的布局之中。

    下边就用codepen代码演示的方式来先简单介绍Flex属性的原理,不同的属性是怎么样使用以及如何影响控制元素的布局的。:

一、基础知识

2.png

    在开始这部分知识介绍之前,我们先来看上面的这张图,简单了解一下Flex布局的盒子模型以及相关的术语:

  • flex盒子模型由容器(flex container)以及容器的直接子元素(flex item)组成。

  • 以容器(flex container)定义,有主坐标(main axis)以及纵坐标(cross axis),主坐标为默认横向,默认从左到右,纵坐标默认为纵向,默认从上到下(当布局排列方式变化的时候,main axis跟cross axis的方向也会跟着变化)

  • 子元素(flex item)在main axis方向的尺寸为main size,在cross axis方向的尺寸为cross size

    如果你想了解有关这方面更详细的信息,可以阅读W3C官方中有关于Flexbox模块的相关资料

二、使用方法(属性介绍)

    这里我们将Flex盒子模型拆分为容器(flex container)和子项(flex item)来分别介绍其拥有的属性,以及使用codepen代码演示的方式来具体介绍flex布局的使用方法。

容器(flex container):

  1. display:

     该属性定义定义了容器是以块状(flex)还是行内元素(inline-flex)的方式显示,改属性的设置能让其子项具有弹性上下文的属性:

    ps:在使用flexbox弹性布局的时候此属性的设置很重要,必不可少

blob.png

    2.flex-direction

    改属性主要决定子项(flex item)在容器内的排列方式:

blob.png

  • row,表示flex items以横向且从左到右的方式排列(ltr)

  • row-reverse,表示flex items以横向且从右到左的方式排列(rtl)

  • column,表示flex items以纵向且从上到下的方式排列

  • column-reverse,表示以纵向且从下到上的方式排列

     3.flex-wrap

    默认情况下会让容器内的子项(flex item)保持在一行内,胆你可以通过这个属性来设置让容器内的子项是否换行(/列),这个属性结合着flex-direction属性可以决定换行后新的一行或一列的排序方式。

    3.png

blob.png

    这个属性对应属性值跟文本是否换行的属性值一致(但这里对应的是换行后新的一行跟上一行的排序方式):

  • nowrap,表示容器内的子项(flex items)保持在一行或一列(当flex-direction为column或column-reverse的时候)不换行(/列)

  • wrap,跟nowrap相反,表示flex items换行或换列,但以默认(左到右或上到下)的方式排列

  • wrap-reverse,表示flex items换行且反向排列(右到左或下到上)  

    4.flex-flow

   改属性是上面两个属性flex-direction和flex-wrap属性的简写方法:

blob.png

 ps:有简写方式的建议尽量使用简写方式,这样可以让你的代码看着更简洁

    5.justify-content

   4.png

    这个属性定义了子项(flex item)在横轴方向的对齐方式,当flex item的尺寸在横轴方向都是不变的或者达到最大尺寸的情况下,用来分配额外剩余的可用空间,或者当flex item在横轴排布要超出容器的时候,进行压缩控制:

blob.png

  •  flex-start(默认值)子项(flex items)在main轴开始方向对齐

  • flex-end,子项(flex items)在main结尾方向对齐

  • center子项(flex items)在main轴居中对齐

  • space-between子项(flex items)始终保持在一行,main轴两端对齐

  • space-around子项(flex items)等间距对齐,但第一个元素距离容器左边的间隔是跟下一个元素间隔的二分之一,因为第一个元素右边有一个单元的间隔,第二个元素左边也有一个单元的间隔

ps:注意这里的开始结尾方向,如果你设置的justify-content值为flex-start,但你的flex-direction值为row-reverse的话,因为子项(flex item)是从右到左排列的,所以开始方向是在右边,所以flex-start的对齐方式应该是右对齐。flex-end的结尾方向也一样,受flex-direction值的影响。结合着flex-wrap属性的话,换行后的元素对齐方式跟第一行一致。

    6.align-items

    5.png

    该属性定义了子项(flex item)在纵轴方向的对齐方式,可以把它想象为justify-content在纵轴方向的定义:

blob.png

  • flex-start,子项(flex item)在cross轴方向以开始方向对齐;

  • flex-end,子项(flex item)在cross轴方向以结尾方向对齐;

  • center,子项(flex item)在cross轴方向居中对齐(该属性值能很方便地让元素在容器内垂直居中对齐

  • baseline,子项(flex item)在cross轴方向以其文本的基准线对齐

  • stretch默认值),子项(flex item)在cross轴方向填满整个容器(当固定尺寸的时候该属性不生效)

上面这个实例中的第一个跟第五个我用了column的排列方向来验证flex-direction值对align-items属性的影响。   

    7.align-content

6.png

    该属性定义的是多行(/多列)的情况下,所有行/列在cross axis方向的对齐方式,跟justify-content(或align-items)对子项(flex item)对齐方式的定义类似,不过justify-content(或align-items)是针对子项(flex item)对齐,而该属性对应的是多行/多列的对齐方式。

blob.png

ps:注意这里justify-content属性跟align-items属性的时候,我没有直接说justify-content是flex items在横轴方向的对齐方式,而是在main axis方向的对齐方向,也没有说align-items是flex items在纵轴方向的对齐方式(或align-content是对多行元素在纵轴方向的对齐方式),同样也是说是在cross axis方向的对齐方式。这是因为当flex-direction是row的时候,main axis是横向的,而当该值为cloumn的时候,main axis则是纵向的。所以justify-content和align-items以及align-content属性对flex items对齐方式的也同样受flex-direction值的影响。上面这个实例中的第五个我用了column的排列方向来验证flex-direction值对align-content属性的影响。

    好了,到这为止,对容器(container)属性的所有介绍就结束了,下边就是对子项(flex item)属性的介绍了。

 子项(flex item):

    1)order

    该属性接收一个整数值(负数也生效),数值越小的子项排在越前:

blob.png

    2)flex-grow

    该属性定义了子项(flex item)在有需要的时候进行尺寸扩展,接收一个无单位的数值作为比例(负数值无效),他决定了该子项占用多少容器内可用的空间。

    当所有的子项(flex item)都是设置了该属性为1的时候,容器内剩余的可用空间就平分给每个子项,当某个子项的flex-grow值为2的时候,该子项就占用两倍于其他子项的可用空间。

blob.png

   3)flex-shrink

    该属性定义了该子项(flex item)在必要时候的收缩属性,跟flex-grow的效果相反,使用方法一致,负数值无效

    4)flex-basis

   定义该子项默认的初始尺寸,它可以是一个长度值也可以是一个关键词,跟width和height属性相同,用来指定子项初始的尺寸值。默认值为auto,但取值为auto的时候,有个待解决的问题

blob.png

     5)flex

    该属性是flex-grow,,flex-shrink,flex-basis三个值的简写方式,默认值为0 1 auto,其中第二三个属性flex-shrink和flex-basis值是可选的:

blob.png

     6)align-self   

 对比align-items属性,我们知道这个是针对某个子项(flex item)在cross axis方向的对齐方式定义,该属性可以覆盖对容器(container)上定义的align-items属性:

blob.png

 ps:在flexbox布局中,float,clear,vertical-align属性对子项(flex item)均无效。    这里有个工具可以让大家能够可视化地去调试Flexbox的各个参数,以及生成对应的代码:简单调试Flexbox属性,以及生成相应的代码工具    好了,终于对子项(flex item)的所有属性也介绍完了,下边我们就将结合了简单的实例来看看flexbox具体能怎么用,有什么用?

三、Flexbox布局的简单应用

1、让一个元素在容器内完美居中:

    在以前我们为了垂直居中用尽各种奇淫技巧的案例,当我们用flexbox布局的时候,简单的几行代码,实现了完美的居中,不管是在水平还是垂直方向,不管是在已知元素尺寸还是未知元素尺寸的情况下,简直就是"完美"7.png

 

    居中的这个在我们实际的需求中有个常见的场景就是在做移动端页面的时候,一个要求水平且垂直居中的浮层:

8、.jpg

 

2、实现一个简单的响应式导航栏

blob.png

   这个例子是大家可以在不同尺寸的屏幕下看到不同的布局方式,在大屏幕下是右对齐在容器的右方,在稍微小一点的屏幕的时候(比如平板),导航居中显示,在更小的屏幕(比如是手机),导航则是每个子项100%的宽度,一个项占一行的方式显示:

9.png

10.png

11.png

    3、实现一个简单的页面布局方式

blob.png

12.png

13.png

14.png

ps:更多的实用案例可以看下这篇国外的文章:Using Flexbox today

四、浏览器支持情况:

     因为这个属性最早在2009年就被提出了,到现在为止经历了各种不同的版本,所以浏览器对不同版本的flexbox支持情况也不一样:

15.png

http://caniuse.com/#feat=flexbox  

  • 1表示只支持旧的文档而且不支持wrapping

  • 2表示只支持2012的语法规范

  • 3表示不支持flex-wrap或flex-flow属性

  • 4表示由于有很多的bug而只是部分支持

五、关于Flexbox的一下bug或一些坑

     关于flexbox在使用的时候,是否要注意一些东西,或者会遇到一些bug,可以参考下边的这些资料:

  1. https://github.com/philipwalton/flexbugs

  2. 使用Flexbox碰到了什么样的坑?

六、参考资料

  1. https://css-tricks.com/snippets/css/a-guide-to-flexbox/  

  2. https://scotch.io/tutorials/a-visual-guide-to-css3-flexbox-properties  

  3. http://flexbox.io/#/auth/f795d7620aa45b7c4c3d220d74952565  

  4. https://www.w3.org/TR/css-flexbox/#box-model  

  5. https://www.w3.org/html/ig/zh/css-flex-1/  

  6. http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html  

  7. https://developer.mozilla.org/en-US/docs/Web/CSS/flex  

  8. http://chriswrightdesign.com/experiments/flexbox-adventures/  

  9. http://www.w3cplus.com/css3/flexbox-adventures.html  

  10. Flexbox,更优雅的布局

  11. css属性列表查询资料

评论