网页布局(layout)是CSS的一个重点,传统的方式是基于盒子模型,依赖display
、position
、float
等属性,对于特殊布局非常不便,比如垂直居中。2009年,W3C提出了Flexbox布局方案,一种简单、完整、响应式的页面布局。
- Flex弹性盒子布局与方向无关,相对于常规布局(垂直块/水平内联块为基础)不存在浮动元素脱离文档流后需清除浮动的问题。
- Flex弹性盒子布局适用于应用程序的组件以及小规模布局,网格布局适用于较大规模的布局。
- Flex弹性布局模块旨在提供一个更加有效地方式来布置,对齐和分布在容器之间的各项内容,即使它们的大小是未知或动态的。
- Flex弹性布局的主要思想是让容器有能力来改变项目的宽度和高度以填满可用空间,主要是为了容纳所有类型的显示设备和屏幕尺寸的能力。
- Flex弹性布局Flexible Box)用来为盒状模型提供最大的灵活性,任何容器都可指定为Flex布局。
Flex弹性盒子布局的原理
Flex弹性盒子布局旨在赋予父容器更改子元素宽高或顺序的能力,来更好地填充剩余可用空间,主要使其自适应不同尺寸的显式设备和屏幕。使用Flexbox弹性盒子布局的父容器会拉伸每个子元素来填充剩余空用空间,或压缩来阻止它们超出父容器。
由于Flexbox弹性盒子布局在方向上是不可预知的,这一点和常规布局不同,常规布局中Block块是基于垂直方向排列的,Inline内联则是基于水平方向的。常规布局在页面中虽然显式没有问题,但缺乏灵活性,因此难以支撑大型复杂应用。特别是响应式自适应方向、大小、伸缩、收缩等变化时。
弹性布局
Flexbox弹性盒子是一个整体模块而非单一属性,它涉及到属性集在容器和项目上的不同设置。
采用弹性布局的元素称为Flex容器(Flex Container),容器的所有子元素自动成为容器成员,称为Flex项目(Flex Item)。
要使用Flexbox弹性盒子布局首先必须让父元素变成一个Flex容器,可以在父元素中显式的设置display:flex
或display:inline-flex
,通过显式声明Flex容器后,一个Flexbox格式化上下文就会立即启动。
Flex弹性盒子布局关键
- Flex容器(Flex Container):父元素显式设置
display:flex
或display:inline-flex
.flex-container{
display:flex;
}
- Flex项目(Flex Items):弹性盒子容器内的子元素
.flex-item{
}
弹性盒子通过设置display
属性值为flex
或inline-flex
将其定义为弹性容器,弹性盒子只定义了弹性项目如何在弹性容器内布局。弹性项目通常在弹性盒子内一行显示,默认每个容器只有一行。
设置为Flex弹性布局后,子元素的float
、clear
、vertical-align
属性将失效。
.flex-container{
display:flex;
}
行内元素也可使用弹性布局
.flex-inline-container{
display:inline-flex;
}
轴(Axis)
在Flex弹性布局的世界中,水平和垂直并非方向概念,而是采用主轴(Main Axis)和侧轴(Cross Axis)来表示。默认主轴即水平方向从左向右,侧轴即垂直方向从上向下。
主轴和侧轴是Flex容器(Flex Container)默认存在两根轴
横轴:水平的主轴(main axis)
主轴的开始位置即与边框的交叉点称为main start
,结束位置叫做main end
。竖轴:垂直的交叉轴(cross axis)
交叉轴的开始位置叫做cross start
,结束位置叫做cross end
。
Flex项目(Flex Item)默认沿着主轴排列,单个项目占据的主轴空间叫做main size
, 占据交叉轴空间叫做cross size
。
弹性项目在主轴方向上的宽度或高度是弹性项目的主轴长度,弹性项目的主轴长度属性是width
或height
属性,具体由主轴方向flex-direction
属性决定。
弹性容器(Flex Container)
Flex容器上的属性共有6个:
属性 | 描述 |
---|---|
flex-direction | 用于控制Flex项目沿着主轴(Main Axis)的排列方向 |
flex-wrap | 设置Flex弹性项目子元素的换行方式,默认为nowrap。 |
flex-flow | 复合属性,flex-direction和flex-wrap的简写形式。 |
justify-content | 设置弹性项目在横轴上的对齐方式 |
align-items | 设置Flex项目在每个Flex行的交叉轴上默认的对齐方式 |
align-content | 仅适用于多行Flex容器,当Flex容器在交叉轴上存在多余空间时,将子项作为整体进行对齐。 |
主轴方向(Flex Direction)
flex-direction
决定主轴(main axis)的方向,即弹性项目(flex item)的排列方向,用于设置或检索弹性盒子对象的子元素在父容器中的位置。
属性值 | 描述 |
---|---|
row | 默认值,弹性项目水平从左到右以左对齐方式排列。 |
row-reverse | 反转水平横向排列,以右对齐从后向前排列,最后一项位于首位。 |
column | 纵向排列 |
column-reverse | 反转纵向排列,从后向前排列,最后一项位于最上层。 |
Flex的主轴是flex-direction
定义的方向,默认为row
,此时交叉轴跟主轴垂直即为column
。若定义flex-direction
主轴方向为column
,则交叉轴为row
。
flex-direction: row | row-reverse | column | column-reverse;
# 默认值,主轴为水平方向,起点为左端。
.flex-container{
display:flex;
flex-direction:row;
}
# 主轴为垂直方向,起点为上端。
.flex-container{
display:flex;
flex-direction:column;
}
# 主轴为水平方向,起点在右端。
.flex-container{
display:flex;
flex-direction:row-reverse;
}
# 主轴为垂直方向,起点为下端。
.flex-container{
display:flex;
flex-direction:column-reverse;
}
例如:自适应导航
.navigation{
display:flex;
flex-flow:row wrap;
justify-content:flex-end;
}
@media all and (max-width:800px){
.navigation{
justify-content:space-around;
}
}
@media all and (max-width:500px){
.navigation{
flex-direction:column;
}
}
项目换行 (Flex Wrap)
默认情况下弹性项目(flex item)排列在一条轴线上
-
flex-wrap
定义了如果在一条轴线上排列不下弹性项目时,如何换行的情况。 -
flex-wrap
规定了Flex弹性容器是单行还是多行,同时横轴(主轴)的方向决定了新行的堆叠方向。
flex-wrap: nowrap | wrap | wrap-revers;
属性值 | 描述 |
---|---|
nowrap | 默认值,设置弹性项目不拆行或不拆列,即弹性项目溢出弹性容器时不换行。 |
wrap | 设置弹性项目在必要时拆行或拆列,即当弹性项目溢出弹性容器时自动换行。 |
wrap-reverse | 设置弹性项目在必要时拆行或拆列并以反转方式排列 |
禁止换行
-
nowrap
是flex-wrap
的默认值,此时弹性容器为单行。
.flex-container{
display:wrap;
flex-wrap:nowrap;
}
自动换行
-
wrap
用于设置弹性容器为多行,此时弹性项目溢出部分会被放置到新行中,弹性项目内部会发生断行。
.flex-container{
display:flex;
flex-wrap:wrap;
}
反转换行:反转换行排列,即上下项目位置交换。
.flex-container{
display:flex;
flex-wrap:wrap-reverse;
}
方向换行 (Flex Flow)
flex-flow
属于复合属性 是flex-direction
属性和flex-wrap
属性的简写方式
flex-flow: <flex-direction> <flex-wrap>;
flex-flow
默认水平排列且不换行row nowrap
.flex-container{
display:flex;
flex-flow: row nowrap;
}
轴对齐
位置 | 水平 | 垂直 |
---|---|---|
(0, 0) | justify-content:flex-start | - |
(1, 0) | justify-content:center | - |
(2, 0) | justify-content:flex-end | - |
(0, 1) | - | align-items:center |
(1, 1) | justify-content:center | align-items:center |
(2, 1) | justify-content:flex-end | align-items:center |
(0, 2) | - | align-items:flex-end |
(1, 2) | justify-content:center | align-items:flex-end |
(2, 2) | justify-content:flex-end | align-items:flex-end |
横轴对齐(Justify Content)
justify-content
定义弹性项目(flex item)在主轴(main axis)上的对齐方式
当弹性容器中多行弹性项目都无法伸缩,或者已经到达弹性容器最大值时,justify-content
属性可协助对剩余可用空间进行分配。当项目项目溢出某行时,justify-content
可在对齐方式上进行控制。
justify-content: flex-start | flex-end | center | space-between | space-around;
对齐方式 | 描述 |
---|---|
flex-start | 默认左对齐 |
flex-end | 右对齐 |
center | 居中对齐 |
space-between | 两端对齐 |
space-around | 留白包围 |
左对齐
弹性项目向行首起始位置对齐,行首第一个弹性项目的主起始位置的边界将于该行主起始位置的边界对齐,后续弹性项目与前个项目对齐。
.flex-container{
display:flex;
justify-content: flex-start;
}
右对齐
弹性项目向行尾结束位置对齐,行首第一个弹性项目的主结束位置边界将与该行主结束位置边界对齐,后续弹性项目与前一个项目对齐。
.flex-container{
display:flex;
justify-content: flex-end;
}
居中对齐
弹性项目向行中央位置对齐,行元素相互对齐并在行中居中对齐,第一个元素与行主起始位置边距等同于最后一个元素与行主结束位置的边距,若剩余空间为负数,则保持两端相等长度的溢出。
.flex-container{
display:flex;
justify-content: center;
}
两端对齐
弹性项目平均分布在行中,第一个元素柏边界与行主起始位置的边界对齐,最后一个元素的边界与行主结束位置的边距对齐,剩余的弹性项目平均分布,并确保两两之间空白空间相等。
若最左边剩余空间为负数,或行中仅有一个元素,则等效于flex-start
。
.flex-container{
display:flex;
justify-content: space-between;
}
留白包围
- 弹性项目平均分布在行内,两端保留的间距是弹性形目之间间距的一半。
- 若最左边剩余空间为负数或行内只有一个弹性项目则等效于`center
.flex-container{
display:flex;
justify-content: space-around;
}
具体对其方式与轴的方向相关,这里假设主轴为从左到右。
纵轴对齐(Align Items)
align-items
属性定义弹性项目(flex item)在交叉轴(cross axis)上如何对齐,用于设置或检索弹性项在纵轴(侧轴)方向上的对齐方式。
align-items: stretch | flex-start | flex-end | center | baseline;
纵轴对齐 | 描述 |
---|---|
flex-start | 顶对齐,弹性项纵轴起始位置边界紧靠该行纵轴起始边界。 |
flex-end | 底对齐,弹性项纵轴结束位置边界紧靠父容器纵轴结束边界。 |
center | 垂直居中,弹性项在该行纵轴上居中放置,若该行尺寸小于弹性项尺寸,则会向两个方向溢出相同的长度。 |
baseline | 基线对齐,若弹性项行内轴与纵轴同为一条则等同于flex-start,其他情况下则将参与基线对齐。 |
stretch | 垂直拉升,若指定纵轴大小为auto则项目边距尽可能接近所在行的尺寸。 |
具体的垂直对其方式与交叉轴的方向有关,假设交叉轴从上到下。
垂直拉伸
- 默认若弹性项目未设置高度或auto,则项目将占满容器高度。
.flex-container{
display:flex;
align-items: stretch;
}
.flex-item{
height:auto;
}
顶对齐
- 交叉轴的起点对齐
.flex-container{
display:flex;
align-items:flex-start;
}
底对齐
- 交叉轴的终点对齐
.flex-container{
display:flex;
align-items: flex-end;
}
垂直居中
- 交叉轴的中点对齐
.flex-container{
display:flex;
align-items: center;
}
例如:搜索表单
<style>
.form{
display:flex;
align-items:center;
}
.form-input{
flex-grow:1;
}
</style>
<form class="form">
<input type="text" name="keyword" class="form-input"/>
<button type="submit" class="form-btn">确定</button>
</form>
默认form
中的input
和button
都是行内块级元素(inline-block),即默认并排在一行上,此时两控件之间存在3px~4px的间隔,这是浏览器内置样式所指定的。
使用display:flex
指定form
使用Flexbox布局后,input
和button
控件间隔消失,因为Flexbox弹性项目之间是不存在间隔的。
在input
控件上使用flex-grow:1
时,input
控件宽度拉伸后占据当前行所有剩余宽度。button
控件未设置则保持flex-grow:0
即本身宽度,不会被拉伸。
此时若button
高度变化则整个form
的高度也会自动跟着变化,因为Flexbox布局默认不改变Flex弹性项目的宽度,但会默认改变弹性项目的高度。如果弹性项目没有显式地指定高度则将占据弹性容器内所有高度。
可为弹性项目设置align-self
属性(默认值为stretch高度自动拉伸)以改变这种默认行为,也可以为弹性容器设置align-items
,容器内所有项目的align-self
将自动继承父元素中的align-items
属性值。这里为弹性容器设置align-items:center
表示容器内所有项目保持垂直居中对齐。
基线对齐
- 项目的第一行文字的基线对齐
.flex-container{
display:flex;
align-items: baseline;
}
多行对齐(Align Content)
align-items
和align-content
都用于定义Flex容器中元素在交叉轴上的对齐方式,align-content
用于设置或检索弹性盒子堆叠伸缩行的对齐方式。
-
align-content
对单行无效,对多行有效。 -
align-content
定义多根轴线的对齐方式,如果弹性项目只有一根轴线,该属性无效。 -
align-content
仅适用于多行Flex容器,即Flex容器中的Flex项不止一行时该属性才有效果。 -
align-content
的作用是当Flex容器在交叉轴上存在多余空间时,会将所有Flex项作为一个整体进行对齐。
align-content: stretch | flex-start | flex-end | center | space-between | space-around;
- flex-start
各行向Flex弹性容器的起始位置堆叠,弹性容器中第一行的侧轴起始边界紧靠在该弹性容器的侧轴起始边界,之后每行都紧靠前一行。
# 以交叉轴的起点对齐
.flex-container{
display:flex;
align-content: flex-start;
}
- flex-end
各行向弹性容器结束位置堆叠,弹性容器最后一行侧轴结束边界紧靠弹性容器侧轴结束边界,之后每行紧靠前一行。
# 以交叉轴的终点对齐
.flex-container{
display:flex;
align-content: flex-end;
}
- center
各行向弹性容器中间位置堆叠,各行两两紧靠同时在弹性容器中居中对齐,同时保持弹性容器侧轴起始内容边界和第一行之间的距离与弹性容器侧轴结束内容边界 与最后一行之间的距离相等。若剩余空间为负数则各行会向两个方向溢出相等距离。
# 以交叉轴的中点对齐
.flex-container{
display:flex;
align-content: center;
}
- stretch
各行拉伸以占据剩余空间,若剩余空间为负数,则等效于flex-start
。其他情况下剩余空间会被所有行平分以扩大侧轴尺寸。
# 默认轴线占满整个交叉轴
.flex-container{
display:flex;
align-content: stretch;
}
- space-between
各行在弹性容器中平均分布,若剩余空间是负数或弹性容器中仅有一行,则该值等效于flex-start
。其他情况下,第一行的侧轴起始边界紧靠弹性容器侧轴起始内容边界,最后一行侧轴结束边界紧靠弹性容器侧轴结束内容边界,剩余行按一定方式在弹性容器中排列,以保持两两之间空间相等。
# 与交叉轴两端对齐,轴线之间的间隔平均分布。
.flex-container{
display:flex;
align-content: space-between;
}
- space-around
各行在弹性容器中平均分布,两端保留子元素之间间距大小的一半儿,若剩余空间为负数或弹性盒子中仅有一行,则等效于center
。其他情况各行按一定方式在弹性容器中排列以保持两两之间相等空间,同时第一行前和最后一行后空间是其他空间的一半儿。
# 每根轴线两侧的间隔相等,轴线之间的间隔比轴线与边框的间隔间隔大一倍。
.flex-container{
display:flex;
align-content: space-around;
}
案例
例如:垂直居中
Flexbox布局出现前要实现元素垂直居中的方式
- 水平居中
- 块级元素 水平居中:
width:100px; height:100px; margin:0 auto;
设置宽高后使用margin: 0 auto
实现 - 行内元素 水平居中:
text-align:center;
- 块级元素 水平居中:
- 垂直居中
- 行内元素 单行 垂直居中:父元素上设置
height
和line-height
两个相等的值即可 - 行内元素 多行 垂直居中:配置使用
table
和table-cell
实现,或添加伪元素占位填充实现。 - 块级元素 固定宽高 垂直居中:借助绝对定位,设置元素的
top:50%;
后在margin-top:-width/2
以实现 - 块级元素 宽高不定 垂直居中:借助绝对定位,设置元素的
top:50%; transform:translateY(-50%)
以实现
- 行内元素 单行 垂直居中:父元素上设置
使用Flexbox布局实现元素的水平垂直居中的方式,只需要在弹性容器内让弹性项目在主轴和交叉轴上分别居中对齐即可。也就使用justify-content
定义弹性项目在主轴上的排列方式为center
,使用align-items
定义弹性项目在交叉轴上的排列方式为center
。
.flex-container{
display:flex;
justify-content:center;
align-items:center;
}
若针对弹性项目本身可使用align-self
属性来覆盖弹性容器的align-items
属性以定义弹性项目在弹性容器内部交叉轴上的排列方式。
.flex-container{display:flex; justify-content:center;}
.flex-item{align-self:center;}
弹性项目(Flex Item)
Flexbox弹性布局最大的特性是让Flex弹性项目可伸缩,也就是让Flex弹性项目的宽度和高度可以自动填充Flex弹性容器剩余空间,或缩小Flex弹性项目以适配Flex弹性容器不足的宽度。这一切都依赖于Flexbox属性中的flex
属性来完成。
一个Flex弹性容器会等比的按照Flex弹性项目的扩展比率来分配Flex弹性容器的剩余空间,也会按照收缩比例来缩小Flex弹性项目,以免Flex弹性项目溢出Flex弹性容器。
Flexbox弹性布局中,flex
属性是flex-grow
(扩展比率)、flex-shrink
(收缩比率)、flex-basis
(伸缩基准)三个属性的简称,这三个属性可以控制一个弹性项目。
- flex-grow 设置弹性项目的扩展比率,让弹性项目伸缩多少弹性容器多余空间。
- flex-shrink 设置弹性项目的收缩比例,让弹性项目减去弹性容器不足的空间。
- flex-basis 设置弹性项目未扩展或收缩前的大小
弹性项目6属性
属性 | 描述 |
---|---|
flex-grow | 扩展比例,默认为0。 |
flex-shrink | 收缩比例,默认为1。 |
flex-base | 用于定义在分配多余空间前,项目占据的主轴空间大小。 |
flex | flex-grow、flex-shrink、flex-basis三个的简写,默认值为 0 1 auto。 |
align-self | 设置单个项目对齐方式 |
order | 设置弹性项排列位置,默认为0,值越小越靠前。 |
剩余空间
在Flexbox布局中,弹性容器包含一个或多个弹性项目,即父容器中的子节点或子元素。弹性容器和弹性项目都由自身的尺寸,因此会出现所有弹性项目尺寸之和大于或小于弹性容器尺寸的情况。
剩余空间
当所有弹性项目尺寸之和小于弹性容器时,弹性容器会存有多余空间没有被填充,这个多余空间被称为弹性容器的剩余空间(Positive Free Space)。空间不足
当所有弹性项目尺寸之和大于弹性容器时,弹性容器将没有足够空间来容纳所有的弹性项目,这多出来的空间称为负空间(Negative Free Space)。
扩展比例(Flex Grow)
flex-grow
属性用于设置弹性项目(Flex Item)的扩展比例,即根据弹性项目设置的扩展因子作为比率来计算并分配剩余空用空间。
flex-grow
主要在父元素宽度大于子元素宽度之和时起作用,用于定义子元素如何分配父元素的剩余空间,默认为0,即默认不会索取父元素的宽度。
flex-grow: <number> (default 0);
-
<number>
使用数值来定义扩展比率,不允许为负数。 -
default 0
默认值为0
若没有显式的为弹性项声明flex-grow
属性,弹性项目是不会拥有分配剩余空间的权利。
flex-grow
不支持负数,默认为0表示不占用父元素剩余空间来扩展自己的宽度。若flex-grow
大于0则Flex容器剩余空间的分配会发生:
- 若只有一个Flex项目设置了
flex-grow
属性- 当
flex-grow
小于1时会分配给它的是“总剩余空间*比例”的计算值 - 当
flex-grow
大于1时则独享剩余空间
- 当
- 若存在多个Flex项目都设置列
flex-grow
属性- 当
flex-grow
总和小于1时分配给元素的是“总剩余空间 * 当前比例值” - 当
flex-grow
总和大于1时则所有剩余空间都被利用
- 当
例如:分配剩余空间
.flex-container{
display:flex;
}
.flex-item:first-child{
flex-grow:1;
}
.flex-item:last-child{
flex-grow:1;
}
.flex-item:nth-child(2){
flex-grow:2;
}
.flex-item:nth-child(3){
flex-grow:1;
}
例如:实现三栏等高布局,两侧宽度固定,中间 一栏占满剩余空间。
.flex-container{
display:flex;
}
.flex-item:first-child, .flex-item:last-child{
width:200px;
}
.flex-item:nth-child(2){
flex-grow:1;
}
弹性项设置flex-grow:1
即可沾满弹性项目水平剩余空间
- 若Flex容器没设置固定高度,Flex容器的高度会自动被最高的Flex项目撑开,同时其他元素高度也会被拉升到Flex容器一样的高度。
- 若Flex容器设置了固定高度,Flex项目高度都设置为
auto
,则所有Flex项目都会自动跟父元素一样高。
flex-grow
和flex-basis
一样只适用于主轴,默认flex-direction:row
时只会影响width
,若flex-direction:column
则此时影响的height
。
收缩比例(Flex Shrink)
flex-shrink
属性适用于弹性容器内的弹性项目,用于设置或检索弹性项目的收缩比例,即根据弹性项目所设置的收缩因子作为比率来收缩空间。
flex-shrink: <number> (default 1);
flex-shrink
默认值为1,若没有显式定义该属性则自动按照默认值1在所有因子相加后计算并收缩空间。当空间不足时,将等比缩小。若弹性项中有一个设置flex-shrink
为0,其他均为flex-shrink
为1,当空间不足时,flex-shrink
属性为0的元素不缩小。
伸缩基准(Flex Basis)
flex-basis
属性用于弹性项目告知父容器,在剩余空间被分配之前先定义子元素的默认尺寸,可指定百分比或rem
等长度长度或auto
关键字。
flex-basis: <length> | auto (default auto);
-
auto
表示无特定宽度值,具体取决于其他属性值。 -
<length>
表示使用长度值来定义宽度,不允许负数。 -
<percentage>
表示使用百分比来定义宽度,不允许为负数。
例如:
.flex-container{
display:flex;
}
.flex-basis-0{
flex-basis:0;
}
.flex-basis-1{
flex-basis:1;
}
.flex-basis-auto{
flex-basis:auto;
}
若flex-basis
设置为0则表示父容器分配剩余空间之前,会将每个子元素的默认尺寸视为0,剩余空间即父容器的全部空间,表现出直接按照flex-grow
值设置的比例分配子元素的大小。
若flex-basis
设置为auto
则表示父容器将每个子元素中的内容作为子元素的默认尺寸,通过计算剩余空间最后将剩余空间按照flex-grow
值得比例平均分配到子元素中除内容以外得空间即padding
。
flex-basis
属性适用于弹性项目,用于设置或检索弹性项目伸缩基准值。 flex-basis
属性定义了在分配多余剩余空间之前,弹性项目占据主轴空间大小。浏览器会根据此属性,计算主轴是否具有多余空间,其默认值为auto
即弹性项目本身大小。
flex-basis
控制一个弹性项目的默认大小,但它可以被其它Flexbox属性影响。若同时为弹性项目设置flex-basis
和width
属性,则flex-basis
会覆盖width
的取值。flex-basis
属性看上去和width
属性可以等价互换,它们之间有什么不同之处呢?
-
flex-basis
是对应于Flex轴线而言的 -
flex-basis
影响弹性项目在主轴上的大小
当保持flex-basis
缩放基准不变的情况下,改变flex-direction
主轴方向此时会发生什么情况呢?此时会发现,flex-basis
是根据flex-direction
的方向的不同来确定width
或height
的,因此必须手动将height
属性切换到width
属性。
例如:
.flex-container{
display:flex;
}
.flex-item:first-child{
}
.flex-item:nth-child(2){
width:70px;
flex-basis:auto;
}
.flex-item:last-child{
width:50px;
flex-basis:100px;
}
- 弹性项目1:
flex-basis
为默认设置auto
,width
为默认设置auto
,因此占据空间由内容所决定。 - 弹性项目2:
flex-basis
设置为auto
,width
设置为70px,内容空间为70px。 - 弹性项目3:
flex-basis
设置为100px,width
设置为50px,flex-basis
覆盖width
,内容空间为100px。
复合属性(Flex)
-
flex
属性适用于弹性项目,用于设置或检索弹性项目如何分配空间。 -
flex
属性是flex-grow
、flex-shrink
、flex-basis
三个的缩写,默认值为0 1 auto
。
flex: none | [flex-grow] || [flex-shrink] || [flex-basis];
-
flex:none
表示计算值为flex: 0 0 auto
-
flex:auto
表示计算值为flex: 1 1 auto
-
flex:1
表示计算值为flex:1 1 0
例如:三栏移动优先布局
.flex-container{
display: flex;
flex-flow: row wrap;
}
.header, .main, .nav, .aside, .footer{
flex: 1 100%;
}
@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;}
}
例如:圣杯布局
互联网早期由于网速限制,经常会出现HTML内容显示出来但样式还未加载完成而导致用户没能最先看到想看的内容,因此Matthew Levine于2006年提出了圣杯布局,即在HTML源码中将用户想看到的内容挪到次要内容的前面。
圣杯布局(Holy Grail Layout)即三三布局,页面从上到下分为三部分分别是头部、躯干、尾部,躯干由水分划分为三部分从左到右依次是导航、主栏、副栏。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>圣杯布局</title>
</head>
<body>
<header>header</header>
<div class="content">
<main>main</main>
<nav>nav</nav>
<aside>aside</aside>
</div>
<footer>footer</footer>
</body>
</html>
body{display:flex; flex-direction:column; min-height:100vh;}
header, footer{flex:1;}
.content{flex:1; display:flex;}
.content nav, .content aside{flex:0 0 12em;}
.content main{flex:auto;}
.content nav{order:-1;}
@media (max-width:768px){
.content{flex:1; flex-direction:column;}
.content nav, .content aside, .content main{flex:auto;}
}
例如:输入框组
<style>
.flex-container{display:flex;}
.flex-1{flex;1;}
</style>
<div class="flex-container">
<span>prepend</span>
<input class="flex-1"/>
<span>append</span>
</div>
例如:悬挂式布局,即主栏的左侧或右侧需添加一栏图片
<style>
.flex-container{display:flex;}
.align-items-start{align-items:flex-start;}
.flex-1{flex;1;}
.media-figure{margin-right:1em;}
</style>
<div class="media flex-container align-items-start">
<img class="media-figure" src="http://www.quanbaike.com/tool/picapi/2d/api.php" width="400"/>
<div class="media-body flex-1">
media body media body media body media body media body
</div>
</div>
例如:底栏固定,页面内容太少无法沾满一屏高度时底栏会被抬高到页面中间。
<style>
.container{display:flex; flex-direction:column; min-height:100vh;}
.flex-1{flex;1;}
</style>
<div class="container">
<header>header</header>
<main class="flex-1">main</main>
<footer>footer</footer>
</div>
例如:两栏布局
两栏布局常用于博客或信息类页面,可分为固定宽度+自适应、不定宽度+自适应两种模式
<div class="container">
<main>main</main>
<aside>aside</aside>
</div>
- 固定宽度+自适应
aside
侧边栏固定宽度为200px,main
主内容区域自适应,main
主内容区域结构靠前是为了优先加载显示,aside
侧边栏可通过设置order
属性来调整。main
主内容区域设置flex-grow:1
表示使该区域填充容器空白空间。使用flex-grow:1
能达到填充弹性容器剩余空间在原因在于侧边栏aside
默认的flex-grow:0
即不伸缩放大,设置主内容区域main
的flex-grow:1
表示放大填充整个空白区域。
.container{display:flex;}
.container main{flex-grow:1;}
.container aside{width:200px; order:-1;}
- 不定宽度 + 自适应
即两栏均采用自适应宽度,可设置主内容区域宽度为侧边栏宽度的倍数来间接实现。
.container{display:flex;}
.container main{flex:2;}
.container aside{flex:1; order:-1;}
例如:弹性盒子自适应
<style>
*{margin:0; padding:0;}
.container{display:flex; flex-wrap:wrap; justify-content:center;}
.item{flex:0 1 300px; margin:20px; padding:20px; box-sizing:border-box; border:3px solid #9db783; background-color:#fdf6e3;}
</style>
<section class="container">
<article class="item">
<span class="title">将进酒</span> <br>
<span class="content">君不见, <br>黄河之水天上来, 奔流到海不复回, <br>君不见,<br> 高堂明镜悲白发, 朝如青丝暮成雪</span>
</article>
<article class="item">
<span class="title">丹歌惊鸿</span> <br>
<span class="content">天地匆匆 惊鸿而过 路有千百个<br>遑遑无归 闲云逸鹤 人间红尘过<br>引势而流 鸿门乱局 各有各选择<br>乾震坎艮 坤巽离兑 定一切生克</span>
</article>
<article class="item">
<span class="title">将进酒</span> <br>
<span class="content">君不见, <br>黄河之水天上来, 奔流到海不复回, <br>君不见,<br> 高堂明镜悲白发, 朝如青丝暮成雪</span>
</article>
</section>
侧轴对齐(Align Self)
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
限制。
排列顺序(Order)
默认情况下Flexbox弹性容器中的弹性项目会按照文档声明的顺序来排列,可使用order
顺序控制弹性项目出现在父容器中的顺序,order
属性值默认为0,order
属性值越小越靠前。
例如:
.flex-container{
display:flex;
}
.flex-item:first-child{
order:-1;
}
.flex-item:last-child{
order:1;
}
案例
音乐播放界面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>文档标题</title>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<main>Item1</main>
<footer>Item2</footer>
</body>
</html>
<body>
<main>
<aside>item 1b</aside>
<section>item 1a</section>
</main>
<footer>Item2</footer>
</body>
<body>
<main>
<aside>item 1b</aside>
<section>
<div>item 1a - A</div>
<div>item 1a - B</div>
</section>
</main>
<footer>Item2</footer>
</body>
基本布局结构
*{box-sizing:border-box;}
html{height:100%}
/*layout*/
body{display:flex; flex-direction:column; background-color:#fff; height:100%; margin:0; font-size:0.9em; color:#222;}
main{flex:1 0 auto; display:flex;}
footer{flex:0 0 90px; display:flex; padding:10px; background-color:rgba(61, 100, 158, .9); color:#fff;}
/*main*/
main aside{flex:0 0 40px; display:flex; flex-direction:column; justify-content:space-around; align-items:center; background-color: #f2f2f2;}
main section{flex:1 0 auto; display:flex; flex-direction:column;}
设置body
为Flexbox容器,footer
吸附底部,main
填满剩余空间。
-
footer
作为弹性项目设置flex
为0 0 90px
表示不缩放并固定为90px高度 -
main
作为弹性项目设置flex
为1 0 auto
其中flex-grow
为1表示填满整个空间,由于部分浏览器中存在Flex项目收缩后会比其内容尺寸小,所以将flex-shrink
设置为0而非默认的1,同时设置flex-basis
为auto
。即告知浏览器自动计算Flex项目大小但禁止收缩。Flex项目会随着浏览器缩放而收缩,因此此时缩放并不是基于flex-shrink
而是基于自动对Flex项目的宽度进行的重新计算即flex-basis:auto
。
固定侧边栏
main aside{
flex:0 0 40px;
display:flex;
flex-direction:column;
justify-content:space-around;
align-items:center;
background-color: #f2f2f2;
}
/*aside*/
aside i{font-size:0.9em;}
-
aside
设置flex
为0 0 40px
表示不会放大或缩小,固定在40px。 -
aside
设置display
为flex
将其转化为Flex容器,并设置其主轴方向flex-direction
为column
为垂直堆放。 -
aside
内弹性项目通过设置justify-content
为space-around
和align-items
为center
将垂直对齐。
<aside>
<i class="fa fa-bars"></i>
<i class="fa fa-home"></i>
<i class="fa fa-search"></i>
<i class="fa fa-volume-up"></i>
<i class="fa fa-user"></i>
<i class="fa fa-spotify"></i>
<i class="fa fa-cog"></i>
<i class="fa fa-soundcloud"></i>
</aside>
设置内容区域
/*content*/
.content .head{flex:0 0 280px; display:flex; padding:40px; background-color:#4e4e4e;}
.content .list{flex:1 0 auto; padding:5px 10px 0;}
/*content head*/
.head img{width:150px;}
.head .info{flex:1 0 auto; display:flex; flex-direction:column; padding-left:50px; font-weight:300; color:#fff; }
.info div:first-child{margin-bottom:auto;}
.info div:last-child{margin-top:0;}
.info div:last-child i{font-size:0.9em; font-weight:300; padding:0 0.7em;}
/*content list*/
.list .item{display:flex; padding:0 20px; min-height:50px;}
.list .item div{flex:0 0 25%;}
<section class="content">
<section class="head">
<img src="https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture" />
<div class="info">
<div>
<div>title</div>
<div>author</div>
<div>datetime</div>
</div>
<div>
<i class="fa fa-play">play</i>
<i class="fa fa-plus">add</i>
<i class="fa fa-ellipsis-h">more</i>
</div>
</div>
</section>
<section class="list">
<div class="item">
<div>title</div>
<div>author</div>
<div>during</div>
<div>cateory</div>
</div>
</section>
</section>
工具
Flexbox布局样例
https://flexbox.webflow.com/
http://www.yyyweb.com/tag/css3
https://c.runoob.com/front-end/61
https://lincenying.github.io/vue2-flex/
https://www.html.cn