CSS(三)flex布局(flex弹性布局详解)

这是一个系列的文章,你也可以查看其他文章:

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 布局以后,子元素的floatclearvertical-align属性将失效。

CSS(三)flex布局(flex弹性布局详解)_第1张图片

容器默认存在两根轴:水平的主轴(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;
}

 

CSS(三)flex布局(flex弹性布局详解)_第2张图片

 

 

2、flex-wrap

定义换行方式。默认不换行nowrap。

.container {
  flex-wrap: nowrap | wrap | wrap-reverse;
}

CSS(三)flex布局(flex弹性布局详解)_第3张图片

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。

CSS(三)flex布局(flex弹性布局详解)_第4张图片

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-growflex-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-growflex-shrinkflex-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也可以用来设置元素宽度。如果元素上同时设置了widthflex-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 不会纳入剩余空间

结果:

CSS(三)flex布局(flex弹性布局详解)_第5张图片

总结:

如果父级的空间足够: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-)

六、参考资料

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

你可能感兴趣的:(CSS)