赞
踩
这是一个系列的文章,你也可以查看其他文章:
0、CSS-预热篇
早期CSS三大难题包括:垂直居中、列等宽和和自适应宽问题(来自winter,哈哈)。
2009年,W3C 提出了一种新的方案----Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。
flex布局是CSS3新增的一维布局,类似的还有GRID布局,是二维布局。如果使用flex解决CSS早期三大难题,难度瞬间降低一半。
flex布局分为容器(container)属性和项目(item)属性。
注意,设为 Flex 布局以后,子元素的float
、clear
和vertical-align
属性将失效。
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start
,结束位置叫做main end
;交叉轴的开始位置叫做cross start
,结束位置叫做cross end
。
项目默认沿主轴排列。单个项目占据的主轴空间叫做main size
,占据的交叉轴空间叫做cross size
。
任何容器都可以设为flex(或者inline-flex)
- .container {
- display: flex; /* or inline-flex */
- }
容器属性有:
项目属性有:
order
flex-grow
flex-shrink
flex-basis
flex
align-self
分别介绍以上容器属性和项目属性。
一、FLEX容器属性
1、flex-direction
项目的排列方向。默认row,即横向水平向右排列
- .container {
- flex-direction: row | row-reverse | column | column-reverse;
- }
2、flex-wrap
定义换行方式。默认不换行nowrap。
- .container {
- flex-wrap: nowrap | wrap | wrap-reverse;
- }
3、flex-flow
flex-direction
属性和flex-wrap
属性的简写形式,默认值为row nowrap
。
- .container {
- flex-flow: <flex-direction> || <flex-wrap>;
- }
4、justify-content
- .container {
- justify-content: flex-start | flex-end | center | space-between | space-around;
- }
项目在main-axis上的对齐方式。默认为flex-start。
5、align-item
项目在cross-axis上的对齐方式。默认flex-start
- .container {
- align-items: flex-start | flex-end | center | baseline | stretch;
- }
6、align-content
定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
- .container {
- align-content: flex-start | flex-end | center | space-between | space-around | stretch;
- }
二、项目属性
1、order
- .item {
- order: <integer>; /* default 0 */
- }
属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
2、flex-grow
- .item {
- flex-grow: <number>; /* default 0 */
- }
flex-grow
属性定义项目的放大比例,默认为0
,即如果存在剩余空间,也不放大。
如果所有项目的flex-grow
属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow
属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
3、flex-shrink
- .item {
- flex-shrink: <number>; /* default 1 */
- }
flex-shrink
属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
如果所有项目的flex-grow
属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow
属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
4、flex-basis
- .item {
- flex-basis: <length> | auto; /* default auto */
- }
flex-basis
属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto
,即项目的本来大小。
5、flex
- .item {
- flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
- }
flex
属性是flex-grow
, flex-shrink
和 flex-basis
的简写,默认值为0 1 auto
。后两个属性可选。
该属性有两个快捷值:auto
(1 1 auto
) 和 none (0 0 auto
)。
本文第三部分单独分析这个属性。
6、align-self
- .item {
- align-self: auto | flex-start | flex-end | center | baseline | stretch;
- }
align-self
属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items
属性。默认值为auto
,表示继承父元素的align-items
属性,如果没有父元素,则等同于stretch
。
三、子项目flex属性详解
flex
是 flex-grow
、flex-shrink
、flex-basis
的缩写。flex-grow、flex-shrink、flex-basis这三个属性的作用是:在flex布局中,父元素在不同宽度下,子元素是如何分配父元素的空间的。
1、 flex-grow
该属性来设置,当父元素的宽度大于所有子元素的宽度的和时(即父元素会有剩余空间),子元素如何分配父元素的剩余空间。flex-grow
的默认值为0,意思是该元素不索取父元素的剩余空间,如果值大于0,表示索取。值越大,索取的越厉害。
举个例子:
父元素宽600px,有两子元素:A和B。A宽为100px,B宽为200px。
则空余空间为600-(100+200)= 300px。
如果A,B都不索取剩余空间,则有300px的空余空间,A、B大小不变。
如果A索取剩余空间:设置flex-grow为1,B不索取。则最终A的大小为 自身宽度(100px)+ 剩余空间的宽度(300px)=400px
如果A,B都索取剩余空间,A设置flex-grow为1,B设置flex-grow为2。则最终A的大小为 自身宽度(100px)+ A获得的剩余空间的宽度(300px * (1/(1+2))),最终B的大小为 自身宽度(200px)+ B获得的剩余空间的宽度(300px * (2/(1+2)))
2、flex-shrink
该属性来设置,当父元素的宽度小于所有子元素的宽度的和时(即子元素会超出父元素),子元素如何缩小自己的宽度的。flex-shrink
的默认值为1,当父元素的宽度小于所有子元素的宽度的和时,子元素的宽度会减小。值越大,减小的越厉害。如果值为0,表示不减小。
举个例子:
父元素宽400px,有两子元素:A和B。A宽为200px,B宽为300px。
则A,B总共超出父元素的宽度为(200+300)- 400 = 100px。
如果A,B都不减小宽度,即都设置flex-shrink为0,则会有100px的宽度超出父元素。
如果A不减小宽度:设置flex-shrink为0,B减小(flex-shrink默认为1)。则最终B的大小为 自身宽度(300px)- 总共超出父元素的宽度(100px)*1= 200px
如果A,B都减小宽度,A设置flex-shirk为3,B设置flex-shirk为2。则最终A的大小为 自身宽度(200px)- A减小的宽度(100px *
(200px *
3/(200 *
3 + 300 *
2))) = 150px,最终B的大小为 自身宽度(300px)- B减小的宽度(100px *
(300px *
2/(200 *
3 + 300 *
2))) = 250px
3、flex-basis
该属性来设置该元素的宽度。当然,width
也可以用来设置元素宽度。如果元素上同时设置了width
和flex-basis
,那么flex-basis
会覆盖width
的值。
分情况讨论
取值顺序为flex-grow、flex-shrink、flex-basis
假设以上三个属性同样取默认值,flex
的默认值是 0 1 auto。
1、当 flex
取值为 none
,则计算值为 0 0 auto,如下是等同的:
- .item {flex: none;}
- .item {
- flex-grow: 0;
- flex-shrink: 0;
- flex-basis: auto;
- }
2、当 flex
取值为 auto
,则计算值为 1 1 auto,如下是等同的:
- .item {flex: auto;}
- .item {
- flex-grow: 1;
- flex-shrink: 1;
- flex-basis: auto;
- }
3、当 flex
取值为一个非负数字,则该数字为 flex-grow
值,flex-shrink
取 1,flex-basis
取 0%,如下是等同的:
- .item {flex: 1;}
- .item {
- flex-grow: 1;
- flex-shrink: 1;
- flex-basis: 0%;
- }
4、当 flex
取值为一个长度或百分比,则视为 flex-basis
值,flex-grow
取 1,flex-shrink
取 1,有如下等同情况(注意 0% 是一个百分比而不是一个非负数字):
- .item-1 {flex: 0%;}
- .item-1 {
- flex-grow: 1;
- flex-shrink: 1;
- flex-basis: 0%;
- }
- .item-2 {flex: 24px;}
- .item-1 {
- flex-grow: 1;
- flex-shrink: 1;
- flex-basis: 24px;
- }
5、当 flex
取值为两个非负数字,则分别视为 flex-grow
和 flex-shrink
的值,flex-basis
取 0%,如下是等同的:
- .item {flex: 2 3;}
- .item {
- flex-grow: 2;
- flex-shrink: 3;
- flex-basis: 0%;
- }
6、当 flex
取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow
和 flex-basis
的值,flex-shrink
取 1,如下是等同的:
- .item {flex: 2 30px;}
- .item {
- flex-grow: 2;
- flex-shrink: 1;
- flex-basis: 30px;
- }
7、flex-basis
规定的是子元素的基准值。所以是否溢出的计算与此属性息息相关。flex-basis
规定的范围取决于 box-sizing
。这里主要讨论以下 flex-basis
的取值情况:
auto
:首先检索该子元素的主尺寸,如果主尺寸不为 auto
,则使用值采取主尺寸之值;如果也是 auto
,则使用值为 content
。
content
:指根据该子元素的内容自动布局。有的用户代理没有实现取 content
值,等效的替代方案是 flex-basis
和主尺寸都取 auto
。
百分比:根据其包含块(即伸缩父容器)的主尺寸计算。如果包含块的主尺寸未定义(即父容器的主尺寸取决于子元素),则计算结果和设为 auto
一样。
举一个不同的值之间的区别:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>Document</title>
- <style type="text/css">
- .parent {
- display: flex;
- width: 600px;
- }
- .parent > div {
- height: 100px;
- }
- .item-1 {
- width: 140px;
- flex: 2 1 0%;
- background: blue;
- }
- .item-2 {
- width: 100px;
- flex: 2 1 auto;
- background: darkblue;
- }
- .item-3 {
- flex: 1 1 200px;
- background: lightblue;
- }
- </style>
-
- </head>
- <body>
- <div class="parent">
- <div class="item-1"></div>
- <div class="item-2"></div>
- <div class="item-3"></div>
- </div>
- </body>
- </html>

主轴上父容器总尺寸为 600px
子元素的总基准值是:0% + auto + 200px = 300px,其中
- - 0% 即 0 宽度
- - auto 对应取主尺寸即 100px
故剩余空间为 600px - 300px = 300px
伸缩放大系数之和为: 2 + 2 + 1 = 5
剩余空间分配如下:
- - item-1 和 item-2 各分配 2/5,各得 120px
- - item-3 分配 1/5,得 60px
各项目最终宽度为:
- - item-1 = 0% + 120px = 120px
- - item-2 = auto + 120px = 220px
- - item-3 = 200px + 60px = 260px
当 item-1 基准值取 0% 的时候,是把该项目视为零尺寸的,故即便声明其尺寸为 140px,也并没有什么用,形同虚设
而 item-2 基准值取 auto
的时候,根据规则基准值使用值是主尺寸值即 100px,故这 100px 不会纳入剩余空间
结果:
总结:
如果父级的空间足够:flex-grow
有效,flex-shrink
无效。
如果父级的空间不够:flex-shrink
有效,flex-grow
无效。
四、前端CSS早期三大难题使用flex解决
1、垂直居中
- .container{
- display:flex;
- justify-content:center;
- align-items:center;
- }
2、多列等高
- .container{
- display: flex;
- }
3、自适应宽
- .container{
- display: flex;
- }
- /**左侧定宽高,右侧设置自适应的元素**/
- .right {
- flex: 1;
- }
五、FLEX浏览器兼容性
-webkit-
)-webkit-
)六、参考资料
1、https://css-tricks.com/snippets/css/a-guide-to-flexbox/
2、https://scotch.io/tutorials/a-visual-guide-to-css3-flexbox-properties
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。