这是一个系列的文章,你也可以查看其他文章:
0、
CSS-预热篇
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 */
}
容器属性有:
-
flex-direction
-
flex-wrap
-
flex-flow
-
justify-content
-
align-items
-
align-content
项目属性有:
-
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浏览器兼容性
- Chrome 29+
- Firefox 28+
- Internet Explorer 11+
- Opera 17+
-
Safari 6.1+ (prefixed with
-webkit-
) - Android 4.4+
-
iOS 7.1+ (prefixed with
-webkit-
)
六、参考资料
2、
https://scotch.io/tutorials/a-visual-guide-to-css3-flexbox-properties