弹性布局(flexbox)模块
弹性布局(flexbox)模块 旨在提供一个更加有效的方式来布置,对齐和分布在容器之间的各项内容,即使它们的大小是未知或者动态变化的。
思想
让容器能够改变其项目的宽度/高度(和顺序),以最好地填充可用空间(主要是为了适应所有类型的显示设备和屏幕尺寸)。
Flex容器扩展项目以填充可用空间,或缩小它们以防止溢出。
最重要的是,flexbox布局与方向无关,而不是常规布局(基于垂直的块和基于水平的内联块)。
虽然这些页面适用于页面,但它们缺乏灵活性(没有双关语)来支持大型或复杂的应用程序(特别是在方向更改,调整大小,拉伸,缩小等方面)。
注意: Flexbox布局是最合适的一个应用程序的组件,以及小规模的布局,而网格布局是用于较大规模的布局。
基础知识
由于flexbox是一个完整的模块而不是单个属性,因此它涉及很多东西,包括它的整个属性集。其中一些意图设置在容器上(父元素,称为“flex容器”),而其他设置意味着设置在子容器上(称为“flex项目”)。
如果“常规”布局基于块和内联流方向,则flex布局基于“flex-flow方向”。请查看规范中的这个图,解释flex布局背后的主要思想。
为了更好理解flexbox布局,这里首先要介绍几个概念:
项目将在main axis(从main-start到main-end)或cross axis(从cross-start到cross-end)之后布局。
(1)主轴(侧轴/十字轴),flexbox布局里面将一个可伸缩容器按照水平和垂直方向分为主轴或侧轴,如果你想让这个容器中的可伸缩项目在水平方向上可伸缩展开,那么水平方向上就是主轴,垂直方向上是侧轴,反之亦然;
(2)主轴(侧轴)长度,当确定了哪个是主轴哪个是侧轴之后,在主轴方向上可伸缩容器的尺寸(宽或高)就被称作主轴长度,侧轴方向上的容器尺寸(宽或高)就被称作侧轴长度;
(3)主轴(侧轴)起点,主轴(侧轴)终点,例如主轴方向是水平方向,通常在水平方向上网页布局是从左向右的,那么可伸缩容器的左border就是主轴起点,右border就是主轴终点,侧轴是在垂直方向,通常是从上到下的,所以上border就是侧轴起点,下border就是侧轴终点;
(4)伸缩容器:如果要构建一个可伸缩的盒子,这些可伸缩的项目必须要由一个display:flex的属性的盒子包裹起来,这个盒子就叫做伸缩容器;
(5)伸缩项目:包含在伸缩容器中需要进行伸缩布局的元素被称作伸缩项目;
明确以上概念之后就可以来构建flexbox布局了;
容器的属性介绍
display: flex | inline-flex; (适用于父类容器元素上)
定义一个flex容器,内联或者根据指定的值,来作用于下面的子类容器。
- box:将对象作为弹性伸缩盒显示。(伸缩盒最老版本)(css3)
- inline-box:将对象作为内联块级弹性伸缩盒显示。(伸缩盒最老版本)(CSS3)
- flexbox:将对象作为弹性伸缩盒显示。(伸缩盒过渡版本)(CSS3)
- inline-flexbox:将对象作为内联块级弹性伸缩盒显示。(伸缩盒过渡版本)(CSS3)
- flex:将对象作为弹性伸缩盒显示。(伸缩盒最新版本)(CSS3)
- inline-flex:将对象作为内联块级弹性伸缩盒显示。(伸缩盒最新版本)(CSS3)
注意:
- css 列(CSS columns)在弹性盒子中不起作用
2.float, clear and vertical-align 在flex项目中不起作用
以下6个属性设置在容器上。
* flex-direction
* flex-wrap
* flex-flow
* justify-content
* align-items
* align-content
1、 flex-direction (适用于父类容器的元素上)
定义:设置或检索伸缩盒对象的子元素在父容器中的位置。
flex-direction: row | row-reverse | column | column-reverse
-
row:横向从左到右排列(左对齐),默认的排列方式。
-
row-reverse:反转横向排列(右对齐,从后往前排,最后一项排在最前面。
-
column:纵向排列。
-
column-reverse:反转纵向排列,从后往前排,最后一项排在最上面。
flex生效需定义其父元素display为flex或inline-flex(box或inline-box,这是旧的方式)
2、 flex-wrap (适用于父类容器的元素上)
定义:设置或检索伸缩盒对象的子元素超出父容器时是否换行。
flex-wrap: nowrap | wrap | wrap-reverse
2.1 nowrap:当子元素溢出父容器时不换行。
2.2 wrap:当子元素溢出父容器时自动换行。
2.3 wrap-reverse:反转 wrap 排列。
3、 flex-flow (适用于父类容器的元素上)
定义:复合属性。设置或检索伸缩盒对象的子元素排列方式。
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
- [ flex-direction ]:定义弹性盒子元素的排列方向。
- [ flex-wrap ]:定义弹性盒子元素溢出父容器时是否换行。
4、 justify-content (适用于父类容器的元素上)
定义:设置或检索弹性盒子元素在主轴(横轴)方向上的对齐方式。
当弹性盒里一行上的所有子元素都不能伸缩或已经达到其最大值时,这一属性可协助对多余的空间进行分配。当元素溢出某行时,这一属性同样会在对齐上进行控制。
justify-content: flex-start | flex-end | center | space-between | space-around
- flex-start:弹性盒子元素将向行起始位置对齐。该行的第一个子元素的主起始位置的边界将与该行的主起始位置的边界对齐,同时所有后续的伸缩盒项目与其前一个项目对齐。
- flex-end:弹性盒子元素将向行结束位置对齐。该行的第一个子元素的主结束位置的边界将与该行的主结束位置的边界对齐,同时所有后续的伸缩盒项目与其前一个项目对齐。
- center:弹性盒子元素将向行中间位置对齐。该行的子元素将相互对齐并在行中居中对齐,同时第一个元素与行的主起始位置的边距等同与最后一个元素与行的主结束位置的边距(如果剩余空间是负数,则保持两端相等长度的溢出)。
- space-between:弹性盒子元素会平均地分布在行里。如果最左边的剩余空间是负数,或该行只有一个子元素,则该值等效于’flex-start’。在其它情况下,第一个元素的边界与行的主起始位置的边界对齐,同时最后一个元素的边界与行的主结束位置的边距对齐,而剩余的伸缩盒项目则平均分布,并确保两两之间的空白空间相等。
- space-around:弹性盒子元素会平均地分布在行里,两端保留子元素与子元素之间间距大小的一半。如果最左边的剩余空间是负数,或该行只有一个伸缩盒项目,则该值等效于’center’。在其它情况下,伸缩盒项目则平均分布,并确保两两之间的空白空间相等,同时第一个元素前的空间以及最后一个元素后的空间为其他空白空间的一半。
5、 align-items (适用于父类容器的元素上)
定义:设置或检索弹性盒子元素在侧轴(纵轴)方向上的对齐方式。
align-items: flex-start | flex-end | center | baseline | stretch
- flex-start:弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴(纵轴)起始边界。
- flex-end:弹性盒子元素的侧轴(纵轴)结束位置的边界紧靠住父容器的侧轴结束边界。
- center:弹性盒子元素在该行的侧轴(纵轴)上居中放置。(如果该行的尺寸小于弹性盒子元素的尺寸,则会向两个方向溢出相同的长度)。
- baseline:如弹性盒子元素的行内轴与侧轴为同一条,则该值与’flex-start’等效。其它情况下,该值将参与基线对齐。
- stretch:如果指定侧轴大小的属性值为’auto’,则其值会使项目的边距盒的尺寸尽可能接近所在行的尺寸,但同时会遵照’min/max-width/height’属性的限制。(默认值)
6、 align-content (适用于父类容器的元素上)
定义:设置或检索弹性盒堆叠伸缩行的对齐方式。
align-content: flex-start | flex-end | center | space-between | space-around | stretch
- flex-start:各行向弹性盒容器的起始位置堆叠。弹性盒容器中第一行的侧轴起始边界紧靠住该弹性盒容器的侧轴起始边界,之后的每一行都紧靠住前面一行。
- flex-end:各行向弹性盒容器的结束位置堆叠。弹性盒容器中最后一行的侧轴起结束界紧靠住该弹性盒容器的侧轴结束边界,之后的每一行都紧靠住前面一行。
- center:各行向弹性盒容器的中间位置堆叠。各行两两紧靠住同时在弹性盒容器中居中对齐,保持弹性盒容器的侧轴起始内容边界和第一行之间的距离与该容器的侧轴结束内容边界与第最后一行之间的距离相等。(如果剩下的空间是负数,则各行会向两个方向溢出的相等距离。)
- space-between:各行在弹性盒容器中平均分布。如果剩余的空间是负数或弹性盒容器中只有一行,该值等效于’flex-start’。在其它情况下,第一行的侧轴起始边界紧靠住弹性盒容器的侧轴起始内容边界,最后一行的侧轴结束边界紧靠住弹性盒容器的侧轴结束内容边界,剩余的行则按一定方式在弹性盒窗口中排列,以保持两两之间的空间相等。
- space-around:各行在弹性盒容器中平均分布,两端保留子元素与子元素之间间距大小的一半。如果剩余的空间是负数或弹性盒容器中只有一行,该值等效于’center’。在其它情况下,各行会按一定方式在弹性盒容器中排列,以保持两两之间的空间相等,同时第一行前面及最后一行后面的空间是其他空间的一半。
- stretch:各行将会伸展以占用剩余的空间。如果剩余的空间是负数,该值等效于’flex-start’。在其它情况下,剩余空间被所有行平分,以扩大它们的侧轴尺寸。(默认值)
项目的属性介绍
以下6个属性设置在项目上。
* order
* flex-grow
* flex-shrink
* flex-basis
* flex
* align-self
1、order属性(适用于弹性盒模型容器子元素)
order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
order:
HTML
<ul id="box" class="box">
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
</ul>
CSS
.box{
display:-webkit-flex;
display:flex;
margin:0;
padding:10px;
list-style:none;
background-color:#eee;
}
.box li{
width:100px;
height:100px;
border:1px solid #aaa;
text-align:center;
}
#box li:nth-child(3){
-webkit-order:-1;
order:-1;
}
2、flex-grow(适用于弹性盒模型容器子元素)
设置或检索弹性盒的扩展比率。根据弹性盒子元素所设置的扩展因子作为比率来分配剩余空间。
flex-grow:
< number>
(default 0)
<number>
:用数值来定义扩展比率。不允许负值- flex-grow的默认值为0,如果没有显示定义该属性,是不会拥有分配剩余空间权利的。本例中b,c两项都显式的定义了flex-grow,可以看到总共将剩余空间分成了4份,其中b占1份,c占3分,即1:3
HTML
<ul id="box" class="box">
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
</ul>
CSS
.box{
display:-webkit-flex;
display:flex;
width:600px;margin:0;padding:10px;list-style:none;background-color:#eee;}
.box li{width:100px;height:100px;border:1px solid #aaa;text-align:center;}
#box li:nth-child(2){
-webkit-flex-grow:1;
flex-grow:1;
}
#box li:nth-child(3){
-webkit-flex-grow:2;
flex-grow:2;
}
3、flex-shrink(适用于弹性盒模型容器子元素)
设置或检索弹性盒的收缩比率(根据弹性盒子元素所设置的收缩因子作为比率来收缩空间。)
flex-shrink:
< number>
(default 1)
- flex-shrink的默认值为1,如果没有显示定义该属性,将会自动按照默认值1在所有因子相加之后计算比率来进行空间收缩。
- 本例中c显式的定义了flex-shrink,a,b没有显式定义,但将根据默认值1来计算,可以看到总共将剩余空间分成了5份,其中a占1份,b占1份,c占3分,即1:1:3
- 我们可以看到父容器定义为400px,子项被定义为200px,相加之后即为600px,超出父容器200px。那么这么超出的200px需要被a,b,c消化
- 按照以上定义a,b,c将按照1:1:3来分配200px,计算后即可得40px,40px,120px,换句话说,a,b,c各需要消化40px,40px,120px,那么就需要用原定义的宽度相减这个值,最后得出a为160px,b为160px,c为80px
HTML
<ul id="flex">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
CSS
#flex{display:-webkit-flex;display:flex;width:400px;margin:0;padding:0;list-style:none;}
#flex li{width:200px;}
#flex li:nth-child(1){background:#888;}
#flex li:nth-child(2){background:#ccc;}
#flex li:nth-child(3){-webkit-flex-shrink:3;flex-shrink:3;background:#aaa;}
4、flex-basis(适用于弹性盒模型容器子元素)
设置或检索弹性盒伸缩基准值。
flex-basis:
<length>
| auto (default auto)
- auto:无特定宽度值,取决于其它属性值
<length>
:用长度值来定义宽度。不允许负值<percentage>
:用百分比来定义宽度。不允许负值
HTML
<ul id="box" class="box">
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
</ul>
CSS
.box{
display:-webkit-flex;
display:flex;
width:600px;margin:0;padding:10px;list-style:none;background-color:#eee;
}
.box li{width:100px;height:100px;border:1px solid #aaa;text-align:center;}
#box li:nth-child(3){
-webkit-flex-basis:600px;
flex-basis:600px;
}
5、flex(适用于弹性盒模型容器子元素)
复合属性。设置或检索伸缩盒对象的子元素如何分配空间。
如果缩写flex:1, 则其计算值为:1 1 0
flex:none | [ flex-grow ] || [ flex-shrink ] || [ flex-basis ]
- none:none关键字的计算值为: 0 0 auto
- [ flex-grow ]:定义弹性盒子元素的扩展比率。
- [ flex-shrink ]:定义弹性盒子元素的收缩比率。
- [ flex-basis ]:定义弹性盒子元素的默认基准值。
HTML
<ul id="box" class="box">
<li>flex:1;</li>
<li>flex:1;</li>
<li>flex:1;</li>
</ul>
<ul id="box2" class="box">
<li>flex:1 0 100px;</li>
<li>flex:2 0 100px;</li>
<li>flex:3 0 100px;</li>
</ul>
<ul id="box3" class="box">
<li>flex:1 1 400px;</li>
<li>flex:1 2 400px;</li>
<li>flex:1 2 400px;</li>
</ul>
CSS
.box{
display:-webkit-flex;
display:flex;
max-width:400px;height:100px;margin:10px 0 0;padding:0;border-radius:5px;list-style:none;background-color:#eee;}
.box li{background:#aaa;text-align:center;}
.box li:nth-child(1){background:#999;}
.box li:nth-child(2){background:#aaa;}
.box li:nth-child(3){background:#ccc;}
#box li:nth-child(1){-webkit-flex:1;flex:1;}
#box li:nth-child(2){-webkit-flex:1;flex:1;}
#box li:nth-child(3){-webkit-flex:1;flex:1;}
#box2 li:nth-child(1){-webkit-flex:1 0 100px;flex:1 0 100px;}
#box2 li:nth-child(2){-webkit-flex:2 0 100px;flex:2 0 100px;}
#box2 li:nth-child(3){-webkit-flex:3 0 100px;flex:3 0 100px;}
#box3{max-width: 800px;}
#box3 li:nth-child(1){-webkit-flex:1 1 300px;flex:1 1 300px;background:#999;}
#box3 li:nth-child(2){-webkit-flex:1 2 500px;flex:1 2 500px;background:#aaa;}
#box3 li:nth-child(3){-webkit-flex:1 3 600px;flex:1 3 600px;background:#ccc;}
说明:
- 上例中,定义了父容器宽(即主轴宽)为800px,由于子元素设置了伸缩基准值flex-basis,相加300+500+600=1400,那么子元素将会溢出1400-800=600px;
- 由于同时设置了收缩因子,所以加权综合可得
300*1+500*2+600*3=3100px
; - 于是我们可以计算a,b,c将被移除的溢出量是多少:
- a被移除溢出量:
300*1/3100*600=3/31
,即约等于58px - b被移除溢出量:
500*2/3100*600=10/31
,即约等于194px - c被移除溢出量:
600*3/3100*600=18/31
,即约等于348px - 最后a,b,c的实际宽度分别为:300-58=242px, 500-194=306px, 600-348=252px
6、 align-self (适用于弹性盒模型容器子元素)
设置或检索弹性盒子元素自身在侧轴(纵轴)方向上的对齐方式。
align-self: auto | flex-start | flex-end | center | baseline | stretch
- auto:如果’align-self’的值为’auto’,则其计算值为元素的父元素的’align-items’值,如果其没有父元素,则计算值为’stretch’。
- flex-start:弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴起始边界。
- flex-end:弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴结束边界。
- center:弹性盒子元素在该行的侧轴(纵轴)上居中放置。(如果该行的尺寸小于弹性盒子元素的尺寸,则会向两个方向溢出相同的长度)。
- baseline:如弹性盒子元素的行内轴与侧轴为同一条,则该值与’flex-start’等效。其它情况下,该值将参与基线对齐。
- stretch:如果指定侧轴大小的属性值为’auto’,则其值会使项目的边距盒的尺寸尽可能接近所在行的尺寸,但同时会遵照’min/max-width/height’属性的限制。
HTML
<ul id="box" class="box">
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
<li>f</li>
<li>g</li>
<li>h</li>
<li>i</li>
</ul>
CSS
.box{
display:-webkit-flex;
display:flex;
-webkit-align-items: flex-end;
height:100px;margin:0;padding:10px;border-radius:5px;list-style:none;background-color:#eee;}
.box li{margin:5px;padding:10px;border-radius:5px;background:#aaa;text-align:center;}
.box li:nth-child(1){
-webkit-align-self: flex-end;
align-self: flex-end;
}
.box li:nth-child(2){
-webkit-align-self: center;
align-self: center;
}
.box li:nth-child(3){
-webkit-align-self: flex-start;
align-self: flex-start;
}
.box li:nth-child(4){
-webkit-align-self: baseline;
align-self: baseline;
padding:20px 10px;
}
.box li:nth-child(5){
-webkit-align-self: baseline;
align-self: baseline;
}
.box li:nth-child(6){
-webkit-align-self: stretch;
align-self: stretch;
}
.box li:nth-child(7){
-webkit-align-self: auto;
align-self: auto;
}
常用例子
1、居中对齐
- 通过设置父类容器的css代码控制子元素的排列方式(flex-direction:row)从左到右(默认方式)。
- 子元素超出内容时是否换行。flex-wrap:wrap(采用换行的方式)。
- 合起来就是flex-flow:row wrap
- 设置子元素的弹性盒堆叠伸缩行的对齐方式为在盒子中平局分布 justify-content:space-around
HTML
<ul class="flex-container">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
<li class="flex-item">6</li>
</ul>
CSS
.flex-container{
padding:0;
margin:0;
list-style:none;
display:-webkit-box;
display:-moz-box;
display:-ms-flexbox;
display:-webkit-flex;
display:flex;
-webkit-flex-flow:row nowrap;
justify-content:space-around
}
.flex-item{
background:tomato;
padding:5px;
width:200px;
height:150px;
margin-top:10px;
line-height:150px;
color:white;
font-weight:bold;
font-size:3em;
text-align:center
}
2、自适应导航
1.设置子元素为从左到右(flex-direction:row),内容超出换行(flex-wrap:wrap).
2.设置子元素的内容向右对齐(justify-content:flex-end)
3.当小于800px时,内容为居中,当小于500px时,内容纵向排列,从上到下。
HTML
<ul class="navigation">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Contact</a></li>
</ul>
CSS
.navigation{
list-style:none;
margin:0;
background:deepskyblue;
display:-webkit-box;
display:-moz-box;
display:-ms-flexbox;
display:-webkit-flex;
display:flex;
-webkit-flex-flow:row wrap;
justify-content:flex-end
}
.navigation a{
text-decoration:none;
display:block;
padding:1em;
color:white
}
.navigation a:hover{background:#00AEE8}
@media all and (max-width:800px){
.navigation{
justify-content:space-around
}
}
@media all and (max-width:600px){
.navigation{
-webkit-flex-flow:column wrap;padding:0
}
.navigation a{
text-align:center;
padding:10px;
border-top:1px solid rgba(255,255,255,0.3);
border-bottom:1px solid rgba(0,0,0,0.1)
}
.navigation li:last-of-type a{
border-bottom:none
}
}
3、常见3栏移动优先布局
1.设置子元素从左到右,超出换行(flex-flow:row wrap;)。
2.默认情况下所有子元素拓展比例为1(flex-grow:1),伸缩比例为100%(flex-basis:100%)。
3.大于800px时,.main的拓展比例为2.伸缩值为0(flex-basis:0px),并且侧栏aside-1排列在第一位,main在第二位,aside-2在第三位。
4.大于600时。.aside元素的拓展比例为1(flex-grow:1),伸缩比例为auto(flex-basis:auto)。
HTML
<div class="wrapper">
<header class="header">Header</header>
<article class="main">
<p>Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
任何一个容器都可以指定为Flex布局。</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
<aside class="aside aside-2">Aside 2</aside>
<footer class="footer">Footer</footer>
</div>
CSS
.wrapper{
display:-webkit-box;
display:-moz-box;
display:-ms-flexbox;
display:-webkit-flex;
display:flex;
-webkit-flex-flow:row wrap;
font-weight:bold;
text-align:center
}
.wrapper > *{padding:10px;flex:1 100%}
.header{background:tomato}
.footer{background:lightgreen}
.main{text-align:left;background:deepskyblue}
.aside-1{background:gold}
.aside-2{background:hotpink}
@media all and (min-width:600px){.aside{flex:1 auto}
}@media all and (min-width:800px){.main{flex:2 0px}
.aside-1{order:1}
.main{order:2}
.aside-2{order:3}
.footer{order:4}
}
浏览器支持
- (现代)是指从最近规范的语法(例如display:flex;)
- (混合)是指从2011个非官方的语法(例如display:flexbox;)
- (旧)从2009以来的语法手段(如display:box;)
Chrome | Safari | Firefox | Opera | IE | Android | ios |
---|---|---|---|---|---|---|
21+ (modern) | 3.1+ (old) | 2-21 (old) | 12.1+ (modern) | 10+ (hybrid) | 2.1+ (old) | 3.2+ (old) |
20- (old) | 22+ (new) |