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

  • Post author:
  • Post category:其他


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

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 */
}

容器属性有:


  • 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-

    )

六、参考资料

1、

2、

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

3、

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



版权声明:本文为u014744118原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。