flex 翻译成中文是弹性。所谓弹性布局是指里面的内容能收缩和扩张,以适应整个容器的宽高。
flex是css display的属性的一个全新的值。它将使用此属性的元素变成了一个flex容器,容器的子元素变成了一个个的flex item。
参考文档:Basic concepts of flexbox(flexbox的基本概述)。
flexbox是一维的布局模型,它提供了非常强大的对其布局的能力。所谓一维的布局,是指flexbox一次只关心一个维度的布局,不是行就是列。与此对比的是:css grid layout ,一个二维的布局,控制着行和列。
flexbox的两条轴线
flexbox上有主轴(main axis)和横轴(cross axis)之分。主轴是依据flex-direction确定的,横轴与它垂直相交。flexbox的布局需要参考两条轴线,所以我们需要了解他们。
主轴
上面也提到了:主轴线是依据flex-direction确定的,flex-direction有四个值:
- row
- row-reverse
- column
- column-reverse
如果设置row或者row-reverse为值,主轴是沿着水平方向延展的。参照下图:
如果设置column或者column-reverse为值,主轴是沿着垂直方向延展的。参照下图:
横轴
横轴与主轴垂直,所以如果flex-direction设置为row或者row-reverse,横轴是垂直方向延展的:
如果设置为column或者column-reverse,横轴是沿着水平方向延展的:
理解轴线,对于排列和对齐flex items是非常重要的。
开始线与结束线
另一个需要重点了解的点是:flexbox没有文档的书写模式。在过去,css严重偏注于横向的、left-to-right的书写模式。现代布局包含了这种模式,我们也不再假定一行文本从左上开始,向右排列,一行结束,从左向右开始新的一行。
下面这篇文章不再细说flexbox和书写模式之前的关系。下面的描述解释了我们为什么不再说那么多的关于从左到右、从上到下的方向的问题。
如果在英文(及其他大部分语文)环境下工作,flex-diretion是row,主轴的开始边缘在左边,结束边缘在右边:
如果我是在阿拉伯语言(习惯从右向左的书写方式)环境下工作,flex-diretion是row,主轴的开始边缘在右边,结束边缘在左边:
由于上面两种语言都是水平的书写模式,两个示例中,横轴的开始边缘都在flex容器的上面,结束边缘在容器的下面。
渐渐地,考虑开始和结束而不是左右就变得正常起来。这样的理解也会对你处理其他的布局方式(例如gird布局,也是同样的处理方式)有帮助。
flex 容器
将一个元素的display属性设为flex或者是inline-flex的时候,这个元素就成为了一个flex容器,其子元素也就成了flex items。CSS所有的属性有一个初始值,对于flex布局也不例外,创建了一个flex容器,它所包含的flex items在初始状态,将如下展示:
- 按行显示(flex-direction的初始值是row)
- items从主轴的开始边缘开始展示
- 在主轴上,items不能延伸,但是可以收缩
- 在横轴上,items会延伸撑满主轴
- flex-basis属性初始值是auto
- flex-wrap初始值是nowrap
综上,最终的items的初始呈现状态是:排列成一行,如果容器的宽度小于内容的宽度,会在行中溢出。如果某些items比较高,其他的items会拉伸,以填充横轴。
下面看个例子:
css代码:
.box { display: flex; }
html代码:
<div class="box"> <div>OneOneOneOneOneOneOneOneOneOneOneOne</div> <div>Two</div> <div>Three <br>has <br>extra <br>text </div> </div>
改变flex方向(flex-direction)
给flex容器添加flex-direction属性,可以概念flex items的显示方向。
- 设置属性值为row-reverse:可以使items以行显示,但是开始和结束的线发生了交换。
- 设置属性值为column,主轴和横轴交换,items会以列显示。
- 设置属性值为column-reverse,主轴横轴交换,同时开始和结束线也交换。
参见如下示例:
css代码:
.box { display: flex; flex-direction: row-reverse; }
html代码:
<div class="box"> <div>One</div> <div>Two</div> <div>Three</div> </div>
多行布局的flex容器(flex-wrap)
当一排显示不了flex items时,flex items会收缩和超出flex容器,为了让flex items全部显示,可以给flex容器设置flex-wrap。它的初始值是nowrap,不换行,设置为wrap后,当items的宽度大于container的宽度后,会自动换行。
示例:
css代码:
.box { display: flex; flex-wrap: wrap; }
html代码:
<div class="box"> <div>One</div> <div>Two</div> <div>Three</div> </div>
flex-flow
flex-flow是flex-direction和flex-wrap的缩写。第一个值为flex-direction,第二个值为flex-wrap。
格式为:flex-flow: row wrap;
flex items
上面提到的flex-direction、flex-wrap是针对flex容器的,flex items也有三个CSS 属性,可以直接对它们进行操作:
- flex-grow
- flex-shrink
- flex-basis
在认识这三个flex属性前,我们需要了解一个概念:可用空间。这三个元素是为了改变可用空间在flex items中的分配情况。可用空间参见下图,假定三个元素的宽度是100像素,那么在初始情况下,可用空间就是剩下的200px。
flex-basis
flex-basis是设置flex items的尺寸,它的初始值是auto。当为auto时,浏览器会首先查看元素是否有尺寸,这意味着,当为元素设置了宽度时,flex-basis的值就为宽度值。当该元素没有尺寸时,flex-basis的尺寸为它的内容的尺寸。
flex-grow
初始值为0,即当可用空间存在时,只显示flex-basis的值。当为正值时,如可用空间存在,就会拉伸以填满容器,所有的元素按照比例拉伸。
flex-shrink
初始值为1,即当容器的尺寸不足以放下全部元素时,items会收缩,以适应容器的尺寸。可为0或者正值,当为正值时,按比例收缩。与flex-grow不同的是,即使设置flex-shrink,items收缩时也不会小于它的最小尺寸,这与flex-grow不同。
flex(grow、shrink、basis)
flex是flex-grow、flex-shrink、flex-basis的缩写。它有已定义的值,分别如下:
- initial:0 1 auto
- auto:1 1 auto
- none:0 0 auto
- <positive-number>:如果是这种的话,如果positive-number为1,则意味着 1 1 0,
flex items的排列、对齐和分布
align-items
规定了如何在横轴上排列items。初始值为:stretch,它会将所有的items的高度拉伸与最高的元素或者容器的高度等高。它可以取如下值:
- stretch 拉伸
- flex-start 从横轴的开始线对齐
- flex-end 从横轴的结束线对齐
- center 在横轴的中心线对齐
当flex-direction为row,align-items为flex-start时,如下所示:
当flex-direction为row,align-items为flex-start时,如下所示:
当flex-direction为row,align-items为center时,如下所示:
align-self
是flex items的css属性,它定义了单个item在横轴上的对齐方式。
align-content
它定义了在横轴上如何给items分配space。
- start
- end
- flex-start
- flex-end
- center
- normal (初始值)
- baseline
- space-between
- space-around
- space-evenly
- sretch
- safe
- unsafe
align-items与align-content的区别
align-content是定义了flex容器的对齐的线,而align-items是在当前的对齐线上对齐items。这意味着align-content的改变,会对align-items产生影响。下面看两种情况,其中align-items不变,为flex-start;而align-content分别为normal(默认值)和start两种情况:
align-content: normal
align-content: start
justify-content
justify-content规定了如何在主轴上对齐元素,初始值是flex-start。它可以取如下的值:
- flex-start
- flex-end
- center
- space-between:当所有的items布局完成后,可将留白space平分到items的space中去,即item与item之间有同等尺寸的space。
- space-around:将单个item的左右两边留出同等的space,每个item的任何一端是一半尺寸的space。
- space-evenly:也将每个item在容器中的左右两边留出同等的space,但是任何一端是全尺寸的space。
当justify-content为space-between时:
当justify-content为space-around时:
当justify-content为space-evenly时:
place-content
是align-content、justify-content的缩写。
总结
将一个元素的display属性设置为flex或者inline-flex,会将其变成一个flex容器,其子元素也变成了flex items。
其中flex容器有如下css属性:
- flex-direction
- flex-wrap
- flex-flow
- align-items
- align-content
- justify-content
flex items有如下css属性:
- flex-basis
- flex-grow
- flex-shrink
- flex
- align-self