这是一个系列的文章,你也可以查看其他文章:
0、CSS-预热篇
1、CSS(一)详解position
2、CSS(二)transform
3、CSS(三)flex布局(flex弹性布局详解)
4、CSS(四)详解Grid布局
5、CSS(五)CSS动画-transition简介
6、CSS(六)CSS动画-animation简介
7、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: || ;
}
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: ; /* default 0 */
}
属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
2、flex-grow
.item {
flex-grow: ; /* default 0 */
}
flex-grow
属性定义项目的放大比例,默认为0
,即如果存在剩余空间,也不放大。
如果所有项目的flex-grow
属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow
属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
3、flex-shrink
.item {
flex-shrink: ; /* default 1 */
}
flex-shrink
属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
如果所有项目的flex-grow
属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow
属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
4、flex-basis
.item {
flex-basis: | 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
一样。
举一个不同的值之间的区别:
Document
主轴上父容器总尺寸为 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
3、http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html