我们知道在 Web 短暂的历史中,设计师用过多种不同的网页布局方式。一开始,设计师依靠 HTML 表格组织内容,把页面分成多行和多列。可是,HTML 中的 table 标签原本就不是为页面布局而生的。后来出现了 CSS 盒基于浮动的布局,使用这种方法控制页面布局更简单,也更加符合逻辑。
如今,基于浮动的布局仍然是最常用的方法,而且设计师一直在改进其用法。例如,栅格系统就是创建布局的得力工具,不过其背后仍然使用的是浮动。再往后,万维网联盟引入了 CSS 定位模块,可以使用相对定位和绝对定位来辅助页面的布局了。至此,在布局的传统解决方案中,有很长一段时间都是基于盒状模型,依赖 display、position 以及 float 属性来进行布局。
但是,这种方式对于那些特殊布局非常的不方便,比如:垂直居中就不容易实现。2009 年,W3C 提出了一种新的方案,Flex 布局----可以简便,完整,响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能了。
Flex 布局已经成为当前布局的首选方案。本文,将从以下几个方面来介绍 Flex 弹性盒布局:
一、Flex 布局是什么?
Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局。
- .box{
- display: flex;
- }
行内元素也可以使用 Flex 布局。
- .box{
- display: inline-flex;
- }
Webkit 内核的浏览器,必须加上-webkit 前缀。
- .box{
- display: -webkit-flex; /* Safari */
- display: flex;
- }
注意,设为 Flex 布局以后,子元素的 float、clear 和 vertical-align 属性将失效。
二、基本概念
采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。
主轴的开始位置(与边框的交叉点)叫做 main start,结束位置叫做 main end;
交叉轴的开始位置叫做 cross start,结束位置叫做 cross end。
项目默认沿主轴排列。单个项目占据的主轴空间叫做 main size,占据的交叉轴空间叫做 cross size。
为了演示上面的属性效果,我们首先建立一个页面,其 HTML 代码片段:
- <body>
- <!-- 容器盒子 -->
- <div class="container">
- <!-- 项目盒子 -->
- <div class="one item">one</div>
- <div class="two item">two</div>
- <div class="three item">three</div>
- <div class="four item">for</div>
- </div>
- </body>
CSS 代码片段:
- <style>
- * {
- margin: 0;
- padding: 0;
- }
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- }
- /* 项目 css */
- .item {
- width: 60px;
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
- /* 每个项目背景颜色 */
- .one {
- background-color: red;
- }
- .two {
- background-color: skyblue;
- }
- .three {
- background-color: gray;
- }
- .four {
- background-color: pink;
- }
- </style>
当前的效果如下:
接下来我们给外层的容器添加 display:flex 后,此时容器就变成了一个弹性盒子。
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- }
当我们设置外层盒子为弹性盒之后,里面的子元素排列成了一行。效果如下:
至此,准备工作已经完成。接下来我们就来具体看一下容器属性和项目属性。
三、容器的属性
以下 6 个属性设置在容器上:
- • flex-direction:设置内部项目的排列方向
- • flex-wrap:设置一行放不下的话是否换行
- • flex-flow:上面两种属性的简写,推荐使用
- • justify-content:项目在主轴( x 轴)上的对齐方式
- • align-items:项目在交叉轴( y 轴)上的对齐方式
- • align-content:有多根轴线时的对齐方式。如果项目只有一根轴线,那么该属性不起作用
3.1 flex-direction 属性
flex-direction 属性决定主轴的方向(即项目的排列方向)。
- .box {
- flex-direction: row | row-reverse | column | column-reverse;
- }
(上图对应的属性值依次为 column-reverse,column,row,row-reverse)
它可能有 4 个值。
- row(默认值):主轴为水平方向,起点在左端。
- row-reverse:主轴为水平方向,起点在右端。
- column:主轴为垂直方向,起点在上沿。
- column-reverse:主轴为垂直方向,起点在下沿。
flex-direction 属性案例展示,flex-direction 属性值为 row-reverse:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- flex-direction: row-reverse; /* 设置弹性盒主轴方向 */
- }
flex-direction 属性值为 column 时的效果如下:
flex-direction 属性值为 column-reverse 时的效果如下:
3.2 flex-wrap 属性
默认情况下,项目都排在一条线(又称"轴线")上。flex-wrap 属性定义,如果一条轴线排不下,如何换行。
- .box{
- flex-wrap: nowrap | wrap | wrap-reverse;
- }
它可能取三个值。
(1)nowrap(默认):不换行。
(2)wrap:换行,第一行在上方。
(3)wrap-reverse:换行,第一行在下方。
flex-wrap 属性案例展示,接下来我们来进行实际的代码演示。首先将项目的宽度设置为 100px,如下所示:
- /* 项目 css */
- .item {
- width: 100px;
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
由于默认情况下 flex-wrap 的属性值为 no-wrap,所以空间不足的情况下会压缩每一个项目,如下图所示:
将容器属性 flex-wrap 设置为 wrap:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- flex-wrap: wrap; /* 设置盒子换行 */
- }
flex-wrap 属性值为 wrap-reverse 时的效果如下:
3.3 flex-flow
flex-flow 属性是 flex-direction 属性和 flex-wrap 属性的简写形式,默认值为 row nowrap 。
- .box {
- flex-flow: <flex-direction> || <flex-wrap>
- }
3.4 justify-content 属性
justify-content 属性定义了项目在主轴上的对齐方式。
- .box {
- justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
- }
它可能取 6 个值,具体对齐方式与轴的方向有关。下面假设主轴为从左到右。
- flex-start(默认值):左对齐
- flex-end:右对齐
- center: 居中
- space-between:两端对齐,项目之间的间隔都相等。
- space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
- space-evenly:均匀排列每个元素,每个元素之间的间隔相等
space-between、space-around、space-evenly,这三个属性都需要容器有剩余空间。
justify-content 属性案例展示,接下来我们来看一下每一种属性值所对应的不同效果。justify-content 属性值为 flex-start 时,代表以左对齐的方式排列。
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- justify-content: flex-start; /* 设置项目的水平对齐方式 */
- }
- /* 项目 css */
- .item {
- width: 60px; /* 将项目的值重新还原为 60px */
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
justify-content 属性值为 flex-end 时,效果如下:
justify-content 属性值为 center 时,效果如下:
justify-content 属性值为 space-between 时,效果如下:
justify-content 属性值为 space-around 时,效果如下:
justify-content 属性值为 space-evenly 时,效果如下:
3.5 align-items 属性
align-items 属性定义项目在交叉轴上如何对齐。
- .box {
- align-items: flex-start | flex-end | center | baseline | stretch;
- }
它可能取 5 个值。具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。
- flex-start:交叉轴的起点对齐。
- flex-end:交叉轴的终点对齐。
- center:交叉轴的中点对齐。
- baseline: 项目的第一行文字的基线对齐。
- stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
align-items 属性案例展示,该属性的默认值为 stretch,这是在项目没有高度的情况下,会撑满整个容器。示例如下:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- }
- /* 项目 css */
- .item {
- width: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
接下来我们来看一下其他值所对应的效果。首先将项目的高度还原为 60px,然后将 align-items 属性值设置为 flex-start,如下:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- align-items: flex-start;
- }
- /* 项目 css */
- .item {
- width: 60px;
- height: 60px; /* 高度还原为 60px */
- text-align: center;
- line-height: 60px;
- color: white;
- }
align-items 属性值设置为 flex-end 时的效果如下:
align-items 属性值设置为 center 时的效果如下:
值为 baseline 时,将以第一行文字的基线来进行对齐。这里我们对第一个项目的字体进行设置,将 font-size 设置为 32px。示例如下:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- align-items: baseline; /* 对齐方式设置为 baseline */
- }
- /* 项目 css */
- .item {
- width: 60px;
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
- /* 每个项目背景颜色 */
- .one {
- background-color: red;
- font-size: 32px; /* 第一个项目字体变大 */
- }
3.6 align-content 属性
align-content 属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
- .box {
- align-content: flex-start | flex-end | center | space-between | space-around | stretch;
- }
该属性可能取 6 个值。
- flex-start:与交叉轴的起点对齐。
- flex-end:与交叉轴的终点对齐。
- center:与交叉轴的中点对齐。
- space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
- space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
- stretch(默认值):轴线占满整个交叉轴。
align-content 属性案例展示,接下来,我们来看一下实际的代码演示。首先我们将项目的 width 设置为 150px,然后设置 flex-wrap 属性值为 wrap,从而得到多个主轴。最后设置 align-content 属性值为 flex-end,如下所示:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- flex-wrap: wrap; /* 设置 wrap 使盒子有多根轴线 */
- align-content: flex-end; /* 多根轴线时的对齐方式 */
- }
- /* 项目 css */
- .item {
- width: 150px; /* 项目宽度设置为 150px */
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
align-content 属性值为 flex-start 时的效果:
align-content 属性值为 center 时的效果:
align-content 属性值为 space-between 时的效果:
align-content 属性值为 space-around 时的效果:
align-content 属性值为 stretch 时的效果:
四、项目的属性
以下 6 个属性设置在项目上。
- • order:项目的排列顺序,数字越小越靠前
- • flex-grow:项目放大的比例
- • flex-shrink:项目缩小的比例
- • flex-basis:项目占据的主轴空间
- • flex:flex-grow,flex-shrink 和 flex-basis 的简写,推荐使用
- • align-self:设置个别项目在交叉轴( y 轴)上的对齐方式
4.1 order 属性
order 属性定义项目的排列顺序。数值越小,排列越靠前,默认为 0。
- .item {
- order: <integer>;
- }
order 属性案例展示,来看一个具体的示例:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- }
- /* 项目 css */
- .item {
- width: 60px;
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
- /* 每个项目背景颜色 */
- .one {
- background-color: red;
- order: 1; /* 将该项目的 order 设置为 1 */
- }
在上面的代码中,我们将项目中的其中一个项目 order 值设置为 1,由于其他项目的 order 值默认都是 0,所以该项目会跑到最后面。效果如下:
4.2 flex-grow 属性
flex-grow 属性定义项目的放大比例,默认为 0,即如果存在剩余空间,也不放大。
- .item {
- flex-grow: <number>; /* default 0 */
- }
如果所有项目的 flex-grow 属性都为 1,则它们将等分剩余空间(如果有的话)。如果一个项目的 flex-grow 属性为 2,其他项目都为 1,则前者占据的剩余空间将比其他项多一倍。
flex-grow 属性案例展示,具体代码如下:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- }
- /* 项目 css */
- .item {
- width: 30px;
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- flex-grow: 1; /* 设置项目的扩展属性为 1 */
- }
- /* 每个项目背景颜色 */
- .one {
- background-color: red;
- flex-grow: 11; /* 单独设置这个项目的扩展属性为 11 */
- }
4.3 flex-shrink 属性
flex-shrink 属性定义了项目的缩小比例,默认为 1,即如果空间不足,该项目将缩小。
- .item {
- flex-shrink: <number>; /* default 1 */
- }
如果所有项目的 flex-shrink 属性都为 1,当空间不足时,都将等比例缩小。如果一个项目的 flex-shrink 属性为 0,其他项目都为 1,则空间不足时,前者不缩小,负值对该属性无效。
flex-shrink 属性案例展示,这里我们首先将项目的宽度设置为 150px,这样容器空间不够会自动压缩项目的宽度。然后我们对其中一个项目的 flex-shrink 属性设值为 0,可以理解为缩小设置为假(false),让该项目不压缩。具体的代码如下:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- }
- /* 项目 css */
- .item {
- width: 150px; /* 将盒子宽度改为 150px,默认一排装不下就会压缩盒子 */
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
- /* 每个项目背景颜色 */
- .one {
- background-color: red;
- flex-shrink: 0; /* 该盒子的 flex-shrink 值设置为 0,表示不压缩该盒子 */
- }
4.4 flex-basis 属性
flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为 auto,即项目的本来大小。
- .item {
- flex-basis: <length> | auto; /* default auto */
- }
它可以设为跟 width 或 height 属性一样的值(比如 350px),则项目将占据固定空间。flex-basis 属性案例展示,来看一个具体的示例。在下面的例子中,我们将项目的宽度设置为 30px,这样一行就会产生剩余空间。接下来我们指定一个项目的 flex-basis 值为 50%,那么该项目就只会伸展至 50% 的空间。
注:可以理解为相比 flex-grow,flex-basis 能够设置分配剩余空间的一部分,而不是全部分配。
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- }
- /* 项目 css */
- .item {
- width: 30px; /* 将盒子宽度改为 30px,这样一行就会产生剩余空间 */
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
- /* 每个项目背景颜色 */
- .one {
- background-color: red;
- flex-basis: 50%; /* 该项目就只会伸展至 50% 的空间 */
- }
4.5 flex 属性
flex 属性是 flex-grow, flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto。后两个属性可选。
- .item {
- flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
- }
该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
注:建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
4.6 align-self 属性
align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。
- .item {
- align-self: auto | flex-start | flex-end | center | baseline | stretch;
- }
该属性可能取 6 个值,除了 auto,其他都与 align-items 属性完全一致。
- auto:自动
- flex-start:交叉轴的起点对齐。
- flex-end:交叉轴的终点对齐。
- center:交叉轴的中点对齐。
- baseline: 项目的第一行文字的基线对齐。
- stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
align-self 属性案例展示,首先我们设置容器的 align-items 属性为 center,表示所有项目的垂直对齐方式为居中对齐。然后单独设置某一个项目的 align-self 属性为 flex-end,和其他盒子的垂直对齐方式不同。具体代码如下:
- /* 容器 css */
- .container {
- width: 300px;
- height: 300px;
- outline: 1px solid;
- margin: 100px;
- display: flex; /* 设置该盒子为弹性盒 */
- align-items: center; /* 设置项目的垂直对齐方式为 center */
- }
- /* 项目 css */
- .item {
- width: 60px;
- height: 60px;
- text-align: center;
- line-height: 60px;
- color: white;
- }
- /* 每个项目背景颜色 */
- .one {
- background-color: red;
- align-self: flex-end; /* 设置该盒子的垂直对齐方式为 flex-end */
- }
总结
1. Flex 布局可以简便,完整,响应式地实现各种页面布局,它已经成为当前布局的首选方案。
2. 任何一个容器都可以指定为弹性盒,只需要将 display 属性设置为 Flex 即可。
3. 采用 Flex 布局的元素,会成为 Flex 容器(Flex container),简称容器。它的所有子元素自动成为容器成员,称之为 Flex 项目(Flex item),简称项目。
4. 学习弹性盒子,其实主要就是学习容器上面可以设置的属性,以及项目上面可以设置的属性。
5. 容器上常见的可设置的属性有 6 个,分别是 flex-direction、flex-wrap、flex-flow、justify-content、align-items 以及 align-content。
6. 项目上常见的可设置的属性也有 6 个,分别是 order、flex-grow、flex-shrink、flex-basis、flex 以及 align-self。