flex布局
flex布局
flex布局体验
传统布局与flex布局
【传统布局】
-
兼容性好
-
布局繁琐
-
局限性,不能在移动端很好的布局
【flex布局】
- 操作方便,布局极为简单,移动端应用很广泛
- PC 端浏览器支持情况较差
- IE11 或更低版本不支持或仅部分支持
建议:
- 如果是 PC 端页面布局,我们还是建议使用传统布局
- 如果是移动端或者不考虑兼容性问题的 PC 端页面布局,推荐使用 flex 弹性布局
初体验
弹性盒
flex
(弹性盒、伸缩盒)
-
是
css
中的又一种布局手段,它主要用来代替浮动来完成页面的布局 -
flex
可以使元素具有弹性,让元素可以跟随页面的大小的改变而改变
弹性容器
要使用弹性盒,必须先将一个元素设置为弹性容器
我们通过display
来设置弹性容器
-
display:flex
设置为块级弹性容器 -
display:inline-flex
设置为行内的弹性容器
弹性元素
-
弹性容器的子元素是弹性元素(弹性项)
-
弹性元素可以同时是弹性容器
1 | <style> |
等间距分布
1 | div { |
平均分为三等分
1 | div { |
flex布局原理
flex 是 flexible Box 的缩写,意为 “弹性布局”,用来为盒状模型提供最大的灵活性,任何一个容器都可以指定为 flex 布局。
- 当我们为父盒子设为 flex 布局以后,子元素的 float(浮动功能)、clear(清除浮动功能)和 vertical-align(垂直居中功能)属性将失效。
- 伸缩布局 = 弹性布局 = 伸缩盒布局 = 弹性盒布局 = flex 布局
采用 flex 布局的元素,称为 flex 容器(flex container),简称 “容器”。它的所有子元素自动成为容器成员,称为 flex 项目(flex item),简称 “项目”。
- 上面的体验中 div 就是 flex 父容器
- 上面的体验中 span 就是子容器 flex 项目
- 子容器可以横向排列也可以纵向排列
【子容器横向排列时的图示】
【总结 flex 布局原理】
就是通过给父盒子添加 flex 属性,来控制子盒子的位置和排列方式。
常见弹性容器属性
以下由 6 个属性是对父元素设置的
flex-direction
:设置主轴的方向justify-content
:设置主轴上的子元素排列方式flex-wrap
:设置子元素是否换行flex-flow
:复合属性,相当于同时设置了 flex-direction 和 flex-wrapalign-content
:设置侧轴上的子元素的排列方式(多行)align-items
:设置侧轴上的子元素排列方式(单行)
flex-direction设置主轴的方向
flex-direction
指定容器中弹性元素的排列方式
(1)主轴与侧轴
在 flex 布局中,是分为主轴和侧轴两个方向,同样的叫法有:行 和 列、x轴 和 y轴
- 默认主轴方向就是 x轴 方向,水平向右
- 默认侧轴方向就是 y轴 方向,水平向下
(2)属性值
flex-direction
属性决定主轴的方向(即:项目的排列方向)
注意:主轴和侧轴是会变化的,就看 flex-direction 设置谁为主轴,剩下的就是侧轴。而我们的子元素是跟着主轴来排列的。
-
row
默认值,弹性元素在容器中水平排列(自左向右) -
row-reverse
弹性元素在容器中反向水平排列(自右向左) -
column
弹性元素纵向排列(自上向下) -
column-reverse
弹性元素反向纵向排列(自下向上)
【案例】
1 | <style> |
1 | flex-direction: row-reverse; |
1 | flex-direction: column; |
justify-content设置主轴上的子元素排列方式
justify-content
属性定义了项目在主轴上的对齐方式
注意:使用这个属性之前一定要确定好主轴是哪个!
属性值 | 说明 |
---|---|
flex-start |
元素沿着主轴起边排列,如果主轴是 x轴,则从左到右(默认值) |
flex-end |
元素沿着主轴终边排列 |
center |
在主轴居中对齐(如果主轴是 x轴 则 水平居中) |
space-around |
空白分布到元素两侧 |
space-between |
先两边贴边再平方剩余空间(重要) |
space-evenly |
空白分布到元素的单侧 |
【案例】
flex-start
元素沿着主轴起边排列
1 | <style> |
flex-end
元素沿着主轴终边排列
center
元素居中排列
space-around
空白分布到元素两侧
space-between
先两边贴边再平方剩余空间
补充
space-evenly
空白分布到元素的单侧
注意:以上例子并不能根据浏览器窗口大小自动调整子项之间的间距,因为父盒子的宽度是固定死 800px 的,假如我们把父盒子宽度设为 80%,那么就可以有效果了。
div {width: 800px;}
div {width: 80%;}
div {width: 80%;}
div span {width: 80%;}
【以上到下为主轴的案例】
1 | /* 我们现在的主轴是 y轴 */ |
1 | /* 我们现在的主轴是 y轴 */ |
1 | /* 我们现在的主轴是 y轴 */ |
盒子自动垂直居中的困扰终于解决啦!!!
1 | /* 我们现在的主轴是 y轴 */ |
1 | /* 我们现在的主轴是 y轴 */ |
flex-wrap设置子元素是否换行
flex-wrap
设置弹性元素是否在弹性容器中自动换行
属性值 | 说明 |
---|---|
nowrap |
默认值,元素不会自动换行 |
wrap |
元素沿着辅轴方向自动换行 |
【案例】
1 | <style> |
1 | flex-wrap: wrap; |
flex-flow复合属性
flex-flow
属性是 flex-direction 和 flex-wrap 属性的复合属性
flex-flow: row wrap;
【案例】
1 | <style> |
align-items设置侧轴上的子元素排列方式(单行)
该属性是控制子项在侧轴(默认是 y轴)上的排列方式,在子项为单项(单行)的时候使用。
属性值 | 说明 |
---|---|
flex-start |
从上到下 |
flex-end |
从下到上 |
center |
挤在一起居中 |
stretch |
拉伸(默认值)注:前提是子盒子没有指定高度,否则没有效果! |
【案例】
flex-start
元素不会拉伸,沿着辅轴起边对齐
1 | <style> |
flex-end
沿着辅轴的终边对齐
center
居中对齐
1 | <style> |
align-items 只能统一对侧轴上的子元素排列方式,假如有多行子元素,要分别对不同的行设置不同的排列方式,那么此种方式就无法做了。
align-content 设置侧轴上的子元素的排列方式(多行)
设置子项在侧轴上的排列方式并且只能用于子项出现 换行 的情况(多行),在单行下是没有效果的。
属性值 | 说明 |
---|---|
flex-start |
在侧轴的头部开始排列 |
flex-end |
在侧轴的尾部开始排列 |
center |
在侧轴中间显示 |
space-around |
子项在侧轴平方剩余空间 |
space-between |
子项在侧轴先分布在两头,再平分剩余空间 |
stretch |
行拉伸以占据剩余空间(默认值) |
【案例】
1 | <style> |
1 | align-content: center; |
1 | align-content: space-around; |
1 | align-content: space-between; |
1 | <style> |
弹性居中
1 | justify-content: center; |
利用弹性盒对元素进行水平垂直双方向居中
align-content和align-items区别
- align-items 适用于单行情况下,只有上对齐、下对齐、居中和拉伸
- align-content 适应于换行(多行)的情况下(单行情况下无效),可以设置上对齐、下对齐、居中、拉伸以及平均分配剩余空间等属性值
- 总结就是单行找 align-items 多行找 align-content
常见弹性元素属性
flex-grow
指定弹性元素的伸展系数,默认值为0flex-shrink
指定弹性元素的收缩系数,默认值为1flex-basis
指定的是元素在主轴上的基础长度flex
flex-grow、flex-shrink、flex-basis 三个属性的合集order
决定弹性元素的排列顺序(前后顺序)align-self
控制子项自己在侧轴的排列方式
伸展系数
flex-grow
指定弹性元素的伸展系数,默认值为0
-
当父元素有多余空间的时,子元素如何伸展
-
父元素的剩余空间,会按照比例进行分配
flex-grow基础
flex-grow 属性定义项目的扩大系数,用于分配容器的剩余空间,那么什么是剩余空间呢?
其实非常简单,剩余空间计算方式就是:
1 | 容器大小 - 所有项目的总大小 |
参考如下示例:
其中:
1 | 1. 每个项目的宽度为50px,3个为150px。 |
1 | 1. 默认为 0 ,即如果容器存在剩余空间,也不放大。 |
那么问题就来了:
1 | 项目是如何根据设置的系数分配剩余空间呢? |
这边涉及到两个关键公式:
1)计算将多少剩余空间拿来分配。
1 | 公式:剩余空间 * ( 所有项目的flex-grow之和 >= 1 ? 1 : 所有项目的flex-grow之和 ) 。 |
这边用了一个三元表达式,理解不难,公式的意思就是说:
如果 所有项目的flex-grow之和 大于等于1,那么就是所有的剩余空间都拿来分配,否则乘以系数即为要分配的剩余空间。
2)计算每个项目分配到多少剩余空间。
1 | 公式:要分配的剩余空间 * ( 单个项目flex-grow / 所有项目的flex-grow之和 ) |
简单的说,就是按照 flex-grow 占比进行分配。
下面我们结合例子进行说明,对这边的计算公式进行理解。
示例1,设置项目的flex-grow为1:
有一个div(容器,450px),容器内包含3个div(项目,各50px)。
1 | .item { |
运行效果:
我们观察到3个项目的宽度都变成了150px,可以看到项目被进行了扩大。
现在套公式看下情况:
1)计算总共要分配多少剩余空间。
1 | 要分配的剩余空间 |
2)计算每个项目分配到多少剩余空间。
因为每个项目flex-grow都为1,所以每个项目分配的剩余空间都一样。
1 | 每个项目分配的剩余空间 |
每个项目多分配100px,加上自身设置的flex-basis,最终每个项目宽度就为150px了。
示例2,设置项目1的flex-grow为1,项目2的flex-grow为2,项目3的flex-grow为3:
我们直接套公式计算:
1)计算总共要分配多少剩余空间。
1 | 要分配的剩余空间 |
2)计算每个项目分配到多少剩余空间。
因为每个项目flex-grow都不一样,所以每个项目分配的剩余空间要分开计算。
1 | 项目1分配的剩余空间 |
所以最终:项目1宽为100px、项目2宽为150px、项目3宽为200px。
写上代码看看效果:
1 | .item { |
运行效果:
观察运行效果,符合预期。
示例3:设置项目1的 flex-grow 为 0.1,项目2的 flex-grow 为0.2,项目3的 flex-grow 为 0.3:
这个示例和上例差不多,只是数字变成了小数,并且总和不大于1。
先套公式来计算一下:
1)计算总共要分配多少剩余空间。
1 | 要分配的剩余空间 |
2)计算每个项目分配到多少剩余空间。因为每个项目flex-grow都不一样,所以每个项目分配的剩余空间要分开计算。
1 | 项目1分配的剩余空间 |
所以最终:项目1宽为80px、项目2宽为110px、项目3宽为140px。
样式代码如下:
1 | .item { |
运行效果如下:
符合计算预期。
flow-grow应用
flow-grow属性在项目中运用很多,比如页面布局、导航条、分页等。
实例1:使用 flex 弹性布局实现如下效果:
这个其实就是腾讯首页的导航条了,我们模拟实现一下,步骤分为4步:
1)首先先写html标签,标签很简单一个 nav 包含若干 a 标签:
1 | <nav class="container"> |
2)设置基本样式,背景、颜色、边框圆角等:
1 | .container { |
运行效果:
3)设置容器为 flex 布局,项目 flex-grow 为1 平分剩余空间:
1 | .container { |
运行效果:
4)再来一个上下居中即可,flex 弹性布局将容器属性 align-items 设置为 center 即可:
1 | .container { |
运行效果:
至此这个例子就完成了。
和之前使用float相比,我们尝试改变容器大小,会发现项目也跟着变化,这个就是弹性的意思了。如下图所示:
总结
- 容器内未被占用的空间称为剩余空间。
- flex-grow用于设置项目的放大系数。
- 项目放大尺寸计算包含两个公式:
1)计算将多少剩余空间拿来分配。
1 | 公式:剩余空间 * ( 所有项目的flex-grow之和 >= 1 ? 1 : 所有项目的flex-grow之和 ) 。 |
2)计算每个项目分配到多少剩余空间。
1 | 公式:要分配的剩余空间 * ( 单个项目flex-grow / 所有项目的flex-grow之和 ) |
- flex-grow不是设置具体的尺寸,在弹性布局中应用广泛。
缩减系数
flex-shrink
指定弹性元素的收缩系数,默认值为1
-
当父元素中的空间不足以容纳所有的子元素时,如何对子元素进行收缩
-
缩减系数的计算方式比较复杂,缩减多少是根据 缩减系数 和 元素大小 来计算
简单的说 flex-grow 用于放大,那么 flex-shrink 就是用于缩小了,两个属性就是反过来,计算方式都类似。放大是因为有剩余空间,缩小就是因为项目的宽度超过容器了,有一个超出空间,所以就要进行缩小。
flex-shrink基础
超出空间计算方式:
1 | 所有项目的总大小 - 容器大小 |
参考如下示例:
容器宽度为450px,三个项目各为200px,总宽超过容器了,就自动缩小了。不难计算,这里超出的空间就是 200px * 3 - 450px = 150px。
其中:
1 | 1. 默认值为1,表示所有项目等比例缩小。 |
缩小的尺寸计算方式和flew-grow类似,涉及到两个公式:
1)计算超出空间中多少用来压缩。
1 | 公式:超出空间 * ( 所有项目的flex-shrink之和 >= 1 ? 1 : 所有项目的flex-shrink之和 ) 。 |
如果没有超出空间,那么就用压缩了;如果超出空间为150px,所有项目的flex-shrink之和为0.6,那么90px用来压缩。
2)计算每个项目缩小多少空间。
1 | 公式:要压缩的空间 * ( 单个项目flex-shrink / 所有项目的flex-shrink之和 ) |
简单的说,就是按照 flex-shrink 占比进行缩小。
下面我们结合例子进行说明,对这边的计算公式进行理解。
示例1,设置项目的 flex-shrink 为0:
接上一篇例子,有一个div(容器,450px),容器内包含3个div(项目,flex-basis 为200px)。
1 | .item { |
flex-shrink 为0表示不压缩项目。
可以看到item3项目那边超出了容器一截。
示例2,接上例,设置项目1、2、3的 flex-shrink 分别为0、1、2:
套公式计算:
1)计算超出空间中多少用来压缩。
1 | 要压缩的空间 |
2)计算每个项目缩小多少空间。
1 | 项目1压缩的空间 |
所以最终:项目1宽为200px、项目2宽为150px、项目3宽为100px。
写上代码看看效果:
1 | .item { |
运行效果:
观察运行效果,符合预期。
示例3:设置项目1、2、3的 flex-shrink 分别为 0.1、0.2、0.3:
这个示例和上例差不多,只是数字变成了小数,并且总和不大于1。
先套公式来计算一下:
1)计算超出空间中多少用来压缩
1 | 要压缩的空间 |
2)计算每个项目缩小多少空间。
1 | 项目1压缩的空间 |
所以最终:项目1宽为185x、项目2宽为170px、项目3宽为155px。
样式代码如下:
1 | .item { |
运行效果如下:
符合计算预期。
总结
- 项目的总大小超出容器部分成为超出空间。
- flex-shrink用于设置项目的缩小系数。
- 项目缩小尺寸计算包含两个公式:
1)计算超出空间中多少用来压缩。
1 | 公式:总超出空间 * ( 所有项目的flex-shrink之和 >= 1 ? 1 : 所有项目的flex-shrink之和 ) 。 |
2)计算每个项目缩小多少空间。
1 | 公式:要压缩的空间 * ( 单个项目flex-shrink / 所有项目的flex-shrink之和 ) |
基础长度
flex-basis基础
flex-basis
指定的是元素在主轴上的基础长度
-
如果主轴是横向的,则该值指定的就是元素的宽度
-
如果主轴是纵向的,则该值指定的就是元素的高度
-
默认值是
auto
,表示参考元素自身的高度或宽度 -
如果传递了一个具体的数值,则以该值为准
在这里可以先理解成 宽(width)属性,用法和 width 的一致,只是优先级比 width 更高。
示例1 有一个div(容器),容器内包含3个div(项目),容器设置为 flex 弹性布局。
容器内项目的宽度是根据内容自适应的,这个也就是 flex-basis 默认值为 auto 的含义了。
下面设置项目的宽度为120px:
1 | .item { |
运行效果:
可以看到3个项目的宽度都为120px了,这个就是 flex-basis 的含义了。
思考:
1 | 如果设置 width: 100px,那么项目实际为多宽呢? |
解答:因为 flex-basis 属性的优先级比 width 高,所以项目的宽度还是120px。
思考:
1 | 设置宽度为什么不直接用 width 属性?还要再多一个 flex-basis 属性,不是多此一举吗? |
解答(难点):
1 | flex-basis 这边并没有说是定义项目的宽度,而是说:占据主轴空间的大小。 |
总结
- flex-basis 属性设置在项目上的。
- flex-basis 是设置项目 占据主轴空间的大小、不全等于width。
- flex-basis 优先级比 width 更高。
flex属性
前面三节讲了 flex-grow、flex-shrink、flex-basis 三个项目属性。
- flex-grow 用于设置项目的放大系数。
- flex-shrink 用于设置项目的缩小系数。
- flex-basis 用于设置项目在主轴上的空间。
那么项目属性 flex 就很简单了,他其实是3个属性的集中而已,语法格式如下:
1 | .item { |
其中:
1 | 1. 这个属性可以独立设置 flex-grow flex-shrink flex-basis 的值,如:1 0 120px。 |
initial
:flex: 0 1 auto
默认值
实务中经常会看到如下样式代码:
1 | .item { |
这个其实就是表示 flex-grow 设置为1,各项目等比例放大。
经常用作自适应布局,内容区会自动放大或缩小占满剩余空间。在chrome浏览器上也可以将flex: 1;
flex: 2;
下面有几个flex布局的常用场景:
1、一个元素宽度(或高度)固定,另一个元素宽度(或高度)自适应。
1 | .parent { |
2、子元素都设置flex: 1; 子元素盒子会平分并占满父盒子;
1 | <div class="container"> |
3、那么如果设置 flex: 1 1 auto;呢? 子元素盒子会根据自己的内容来适配并一起占满整个空间;
1 | <div class="container"> |
order属性定义项目的排列顺序
order 用于是设置项目的排序顺序,从小到大排列。
项目的排序默认会按照html的结构进行排序,如果需要定义排序顺序,可以通过order属性定义项目的排序顺序,语法格式如下:
1 | .item { |
其中:
1 | order 为整数,可以为负数。 |
如果之前有学习过sql,那么对 order 就很熟悉了。因为sql中排序的关键词就是 order by。
示例1:有一个div(容器,450px),容器内包含5个div(项目,flex-grow 为1)。
1)和前面章节相比多两个项目,方便看出排序效果。
未设置排序前的效果:
2)默认所有的项目 order 值都为0,设置项目1为99,项目3为-1,项目4为-2:
因为项目是按照order从小到大排列,那么正常显示的顺序应该是:
1 | 项目4、项目3、项目2、项目5、项目1。 |
写上代码:
1 | .item1 { |
运行效果:
align-self属性
项目属性 align-self,和 align-items 类似。align-items设置在容器上,作用所有的项目。align-self 设置在项目上,作用单个项目
align-self 属性用来设置项目在辅轴方向上的对齐方式,设置在项目上,作用单个项目。
而 align-items 设置在容器上,作用所有的项目。
语法格式如下:
1 | .item { |
其中:
1 | 1. auto 表示继承容器的 align-items 属性。(默认值) |
示例1,有一个div(容器,450px),容器内包含3个div(项目,flex-basis 为50px),设置 align-items 为 flex-start,项目1的align-self设置为 flex-end:
1 | .container { |
运行效果:
本节总结
- align-self 和 align-items 类似,默认值为auto,表示继承 align-items 的属性。
- align-self 设置在项目上,作用单个项目。align-items设置在容器上,作用所有的项目。