从双飞翼、圣杯布局认识flex布局

还记得当初学布局的时候。。接触最多的就是双飞翼布局和圣杯布局,当然还有一个负margin布局。

margin布局

两边无缝隙,中间有间隙的负margin布局
在JSbin上查看code


圣杯布局

中间自适应,两边固定宽度的圣杯布局 中间自适应,两边固定宽度的圣杯布局
在JSbin上查看code


双飞翼布局

中间自适应,两边固定宽度的双飞翼布局
中间自适应,两边固定宽度的圣杯布局
在JSbin上查看code


每次回想起来做双飞翼和圣杯布局的时候 为了实现它都会写下不下十几行的CSS代码,感觉特别麻烦,下面给大家推荐CSS3新增加的一个布局方法————flex布局。


flex布局

关于flex 布局阮一峰的一片博客 基本上已经是范文了。讲的特别清楚。不过为了加深印象,这里还是返璞归策划,从头总结一下。

什么是flex布局

flex布局,简单来说就是CSS3新出的一个布局方式。使用方法也很简单。根据浏览器的版本分为以下几种定义方式:
0_1466262670353_upload-1071233b-cdbe-4265-addb-8cce2599645f
这里大意就是说:一般来说flex布局定义方式有三种.

  • 第一种真的比较新的浏览器:display:flex
  • 第二种就是版本趋于两者之间的浏览器:display: flexbox
  • 第三种就是老版本的浏览器:display:box

0_1466263672128_upload-0fac61bb-1254-4034-bcce-1d991f696c1d
另外从canIuse上面可以看到,flex对于IE浏览器基本上十分的不友好,只兼容到IE10。另外不同浏览器之间也是需要添加前缀。

flex的基本概念

0_1466264028594_upload-7ab23129-a68d-4aab-897f-08b9b989668f
从这副图 我们可以知道一些大致的内容:

  • 如果把flex布局之后的元素定义为容器。它的子元素就自动成为它的容器成员。
  • 容器默认存在两个两根轴,一个水平方向上的main axis(主轴),一个垂直方向的cross axis(交叉轴)

flex的一些基本属性。

这里简单总结一下flex的基本属性:

flex-direction 定义项目的排列方向(作用于容器)

0_1466264524199_upload-f5d79021-33c6-47e0-bdb1-22c454c29bf8
这个看图很好理解 flex-direction字面意思就是(flex布局的方向)

1
2
3
.item{
flex-direction:row|row-reverse|column|column-reverse
}


order 定义项目的排列顺序。(作用于项目)

0_1466264755790_upload-e2d1f74e-c40a-4bf4-a643-a0fc544072ca
order是一个排序属性,可以这样理解,相当于我们平时站对一样。”个高的在后面,个字矮的在前面”

1
2
3
.item{
order:number;
}


flex-grow定义项目的放大比例。(作用于项目)

0_1466264956662_upload-9d07446c-4500-42a7-aae1-2172902ca8e8
具体使用方法是

1
2
3
.item{
flex-grow:number
}

如果项目flex-grow都为1,即项目均分剩余空间,如果一起为2,其他为1,则前者占据剩余空间为其他的两倍。

额外提一点

还得及之前的例子,我们再做三列布局的时候,或者是左边固定宽度,右边自适应的的布局的时候,每次都要写很多代码。使用flex只需要几行代码
0_1466320091553_upload-8349a97c-6b6c-4438-9598-79f623a04fc2
JS查看源代码


flex-wrap定义项目如何排列(作用于容器)

0_1466320469496_upload-2249fbc0-9103-4c8b-b205-6f0b02be6ee7

具体使用方法:

1
2
3
4
5
6
.item{
flex-wrap:nowrap|wrap|wrap-reverse
}
nowrap:定义flex容器为当行.(项目可能会移除容器)
wrap:定义flex为多行.(第一排,排不下了,就排到第二行)
wrap-reverse:反转排行。

JSbin查看源代码


flex-flow定义项目如何排列(复合属性)

flex-directionflex-wrap组合在一起的属性.这里不做演示。


flex-shrink定义项目的缩放比例(作用于项目)

0_1466322020365_upload-0b056342-1df6-4ee4-9a75-2391771dfcd0

具体使用方法:

1
2
3
.item{
flex-shrink:number
}

0_1466323097627_upload-156f442b-17ce-47a4-85d5-fe1f5354577e
JSbin查看源代码
定义第二个项目flex-shrink的值为2,其他项目默认flex-shrink的值为1,则相当于容器被评分为四块。但是
当我们定义容器宽度width:500px;,然后定义项目width:200px这里我们看到。这三个的项目感觉都被压缩了。分别都各有不同程度的缩小。

这里是什么原因呢?

这里出现这样的情况,原因主要是:当容器被定义display:flex属性之后,默认不会换行,除非在容器上定义flex-wrap:nowrap之外的属性。那么既然默认不换行,就只能用第二种方法压缩

为了探讨压缩率,我把上面这个代码做出一个调整,让第三个项目的flex-shrink:6,我们发现改变后变成这样:
0_1466324164311_upload-6a6f2337-2695-48f3-912f-fcfa48d9f65d
我们会发现这时候和原来相比。第一个项目的长度增长了一部分。项目2和原来项目有明显增长,项目3长度收缩到比项目2还短。
通过上面的例子 可以推理出

  • 我们看到父容器定义为500px,项目定义为200px,则相加之后为600px,超出父容器100px只能通过项目来分担了。
  • 项目1被移除的溢出量=100*1/5=20px;
  • 项目2被移除的溢出量=100*3/5=60px;
  • 项目3被移除的溢出量=100*1/5=20px;

另外flex-shrink定义的是容器空间不足时,项目的缩放比例,让容器空间足够大的时候并不会触发此属性。


flex作用于项目(复合属性)

flex-growflex-shrinkflex-basis的复合属性。
其中flex-basis的作用于width类似.不过当两者同时存在时,优先级高于width。关于三者的区别,这篇博客已经给出了很好的说明:
深入理解flex三属性的区别


justify-content定义项目在主轴上的对其方式(作用于容器)

0_1466337470881_upload-64117cd8-b06a-4ccd-a81d-963a06740998


align-items定义项目在垂直轴上的对齐方式(作用于容器)

0_1466337715209_upload-f96d89e2-57e4-4db8-91a9-c2d10a4161f9
另外如何要单独定义项目的排列方式.可以使用align-self参数和前者一致。
0_1466338643535_upload-006ad0f8-b55c-42d7-b4d3-54019b159d2a
JSbin查看代码

如何让一个div元素做到垂直居中.

到现在 如果别人问你如何让一个div元素垂直居中。
html代码

1
2
3
4
5
6
<div class="wrap">
<div class="show">
我要垂直居中
</div>
</div>
</body>

我想应该有这几种方法:

  • (目标元素定宽高)使用table 布局:具体代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    .wrap{
    width:300px;
    height:300px;
    border:1px solid black;
    display: table-cell;
    vertical-align: middle;
    }
    .show{
    width:50px;
    height:50px;
    margin:0 auto;
    background:red;
    }
  • (目标元素定宽高)使用定位.具体代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    .wrap{
    width:300px;
    height:300px;
    border:1px solid black;
    position:relative;
    }
    .show{
    width:50px;
    height:50px;
    background:red;
    position: absolute;
    left:50%;
    top:50%;
    margin-left:-25px;
    margin-top:-25px;
    }
  • (目标元素可以不确定宽高)使用css3(兼容性不如第二个)
    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    .wrap{
    width:300px;
    height:300px;
    border:1px solid black;
    position:relative;
    }
    .show{
    width:50px;
    height:50px;
    background:red;
    position: absolute;
    left:50%;
    top:50%;
    -webkit-transform: translate(-50% -50%);
    -ms-transform: translate(-50% -50%);
    -o-transform: translate(-50% -50%);
    transform: translate(-50%,-50%);
    }
  • 使用flex弹性布局(这个兼容性更差)代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    .wrap{
    width:300px;
    height:300px;
    border:1px solid black;
    display: flex;
    justify-content: center;
    align-items: center;
    }
    .show{
    width:50px;
    height:50px;
    background:red;
    }

用flex 做出一个双飞翼布局

html代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<header>
我来组成头部
</header>
<div class="wrap">
<main>
我是主要内容,优先加载
</main>
<nav>
我是导航栏(固定宽度)
</nav>
<side>
我是侧边栏,我出现在左边(固定宽度)
</side>
</div>
<footer>
我来组成页脚
</footer>

CSS代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
header,footer{
min-height: 100px;
text-align: center;
line-height: 100px;
clear: both;
background:#aaa;
}
.wrap{
display: flex;
}
main{
flex-grow:1;
background:red;
height:100px;
}
.wrap nav,.wrap side{
flex:0 0 200px;
background:green;
height:100px;
}
.wrap side{
order:-1;
}

最后提一点

设置在容器上的属性:

  • flex-direction(定义项目的排列顺序——主轴);
  • flex-wrap(定义项目排列是否分行——默认不分行);
  • flex-flow(前者的两个复合属性);
  • justify-content(定义项目在主轴的对其方式);
  • align-items(定义项目在垂直轴的对齐方式);
  • align-content(多根轴线的对齐方式)

设置在项目上的属性:

  • order项目的”牌号”顺序(小的在前面,大的在后面)
  • flex-grow定义项目的放大比例。
  • flex-shrink定义项目的缩放比例
  • flex-basis定义项目的width
  • flex(前面三个的复合属性)
  • align-self(单独定义align-self的主轴排列方式)

关于flex布局先总结到这里- -