Flex 布局,即 Flex Box(弹性布局),是一种较为灵活、强大的页面 CSS 布局方式。在深入学习 Flex 布局前,我们需要了解一些 Flex 相关的概念和术语。
Flex 布局的优点:
- 简便、完整、响应式
- 浏览器支持良好
- 传统盒状模型中,难以实现的垂直等布局等 ,Flex布局可以完美解决。
一、基础概念
首先,我们需要了解一下 Flex 布局中的一些概念和术语:
- flex 容器(flex container)
- flex 项目(flex item)
- 主轴(main axis)
- 交叉轴(cross axis)
- 占用主轴空间(main size)
- 占用交叉轴空间(cross size)
- 线轴起止点(main start、main end、cross start、cross end)
在图1-1 非常清晰的展示了这些概念的相互关系。
图1-1 Flex 容器
1.1 容器与项目
使用 Flex 布局的元素(display: flex),称之为 Flex 容器(Flex Container),简称 "容器"。Flex 的布局发生在父容器和子容器之间,因此,元素一旦被申明为 Flex 布局后,它的所有子元素自动成为容器成员。通常,我们将容器内的成员统称为 Flex 项目(Flex item),简称 "项目"。
本文约定:"容器" 指的是 Flex 容器;"项目" 指的是 Flex 项目。
1.2 主轴、交叉轴
容器中默认存在两条线轴,即:水平方向的主轴(main axis)、垂直方向的交叉轴(cross axis)。
- main axis:主轴,水平方向。
- cross axis:交叉轴,垂直方向。
1.3 轴线起始位置
- main start:主轴开始位置
- main end:主轴结束位置
- cross start:交叉轴开始位置
- cross ennd:交叉轴结束位置
1.4 主轴、交叉轴空间
项目(flex item)默认是沿主轴方向排列的,单个项目占据主轴的空间称之为 main size,占据交叉轴的空间称之为 cross size
二、容器、项目属性
本小节,主要介绍一下 Flex 容器的 6 个属性以及 Flex 项目的 6 个属性。通过本章节,相信你会加深对 Flex 布局理解。为了形象说明这些属性的含义,作者 Billow 尽可能在每个示例中做到图文并茂。
2.1 容器属性
通过下面的表格,从整体上了解一下容器的属性。
属性 | 取值 | 说明 |
---|---|---|
flex-direction |
row (默认,从左到右) row-reverse (从右到左) column (从上到下) column-reverse (从下到上) |
容器在哪个方向上排列flex项目 |
flex-wrap |
nowrap (默认,不换行) wrap(换行) wrap-reverse(反向换行) |
flex项目在一个轴线排不下情况,该如何换行。 |
flex-flow |
<flex-direction> <flex-wrap> | flex-direction 与 flex-wrap 的缩写形式。 |
justify-content |
flex-start(默认,左对齐) flex-end(右对齐) center(居中) space-between space-around |
flex项目在主轴上的对齐方式。 |
align-items |
flex-start flex-end center stretch baseline |
定义项目在交叉轴上对齐方式 |
align-content |
flex-start flex-end center space-between space-around stetch |
定义多条线轴对齐方式,若只有一条线轴。 若仅有一条线轴,该属性无效。 |
flex-direction 属性定义了在哪个方向上排列我们的flex项目。flex-direction有四个取值,分别为:
取值 | 说明 |
row | 水平方向,由左到右。(默认) |
row-reverse | 水平方向,从右到左。 |
column | 垂直方向,从上到下。 |
column-reverse | 垂直方向,由下到上。 |
图2-1 容器定义 flex-direction 示例图
图2-1 完整代码:
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container-row {
display: flex;
flex-direction: row;
}
.flex-container-row-reverse {
display: flex;
flex-direction: row-reverse;
}
.flex-container-column {
display: flex;
flex-direction: column;
}
.flex-container-column-reverse {
display: flex;
flex-direction: column-reverse;
}
.flex-item {
border:1px solid #fff;
height:60px;
width:60px;
text-align:center;
line-height:60px;
background: #f66;
color:white;
}
.flex-item.blue {
border:1px solid #fff;
background: #33f;
}
</style>
</head>
<body>
<div class="flex-container-row">
<div class="flex-item">1.刘邦</div>
<div class="flex-item">2.吕雉</div>
<div class="flex-item">3.项羽</div>
<div class="flex-item">4.虞姬</div>
</div>
<div class="flex-container-row-reverse">
<div class="flex-item blue">伯</div>
<div class="flex-item blue">仲</div>
<div class="flex-item blue">叔</div>
<div class="flex-item blue">季</div>
</div>
<div class="flex-container-column">
<div class="flex-item">金</div>
<div class="flex-item">银</div>
<div class="flex-item">铜</div>
</div>
<div class="flex-container-column-reverse">
<div class="flex-item blue">苏洵</div>
<div class="flex-item blue">苏轼</div>
<div class="flex-item blue">苏辙</div>
</div>
</body>
</html>
flex-wrap 定义了项目在轴线上的排列方式,在默认情况下,项目都排列在一条轴线上,不会换行,可以通过 flex-wrap 来定义换行的方式。
取值 | 说明 |
nowrap | 默认值,不换行 |
wrap | 项目沿着轴线方向排列,一行排不下后,换行排列。 |
wrap-reverse | 反向换行。例如:在主轴线上,第一行会在第二行的下放。 |
图2-2 容器定义 flex-wrap 示例
图2-2 完整代码:
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container-nowrap {
display: flex;
flex-wrap: nowrap;
}
.flex-container-wrap {
display: flex;
flex-wrap: wrap;
margin-top:10px;
}
.flex-container-wrap-reverse {
display: flex;
flex-wrap: wrap-reverse;
margin-top:10px;
}
.flex-item {
border:1px solid #fff;
height:60px;
width:120px;
text-align:center;
line-height:60px;
background: #f66;
color:white;
font-size:18px;
}
.flex-item.blue {
border:1px solid #fff;
background: #33f;
}
.flex-item.gray {
border:1px solid #fff;
background: #666;
}
.flex-item.circle {
border-radius: 10%;
}
h3 {
color: #666;
}
</style>
</head>
<body>
<h3>nowrap</h3>
<div class="flex-container-nowrap">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
</div>
<h3>wrap</h3>
<div class="flex-container-wrap">
<div class="flex-item gray">1</div>
<div class="flex-item gray">2</div>
<div class="flex-item gray">3</div>
<div class="flex-item gray">4</div>
<div class="flex-item gray">5</div>
<div class="flex-item gray">6</div>
<div class="flex-item gray">7</div>
<div class="flex-item gray">8</div>
</div>
<h3>wrap-reverse</h3>
<div class="flex-container-wrap-reverse">
<div class="flex-item blue circle">1</div>
<div class="flex-item blue circle">2</div>
<div class="flex-item blue circle">3</div>
<div class="flex-item blue circle">4</div>
<div class="flex-item blue circle">5</div>
<div class="flex-item blue circle">6</div>
<div class="flex-item blue circle">7</div>
<div class="flex-item blue circle">8</div>
</div>
</body>
</html>
值得注意的是,当我们将 flex-wrap 设置为 nowrap 后,并将每一个项目的宽度设置为 120px ,但是,但主轴宽度无法容纳所有项目后,项目的实际宽度会被收缩,在flex项目属性中,我们会详细解释。
2.1.3 flex-flow
flex-flow 是 flex-direction 与 flex-wrap 的缩写形式。
语法:flex-flow: <flex-direction> <flex-wrap>
例子:
flex-flow: row nowrap (默认值,项目沿着主轴排列,不换行。)
flex-flow: column wrap-reverse(项目沿着交叉轴排列,反向换行)
2.1.4 justify-content
justify-content 定义了项目在主轴上的对齐方式。共有5个取值,如下表所示。
取值 | 说明 |
flex-start | 左对齐 |
flex-end | 右对齐 |
center | 居中 |
space-between | 两端对齐,项目间隔相等 |
space-around | 项目间隔相等,两端也有间隔。 |
图2-3 容器定义 justify-content 示例
下图很好的解释了 space-between 与 space-around 的区别,space-between 会使项目两端对齐,并且项目之间的间距相同。space-around 同样会是的项目间距相同,不同之处是与两端也会有间距。
可以看出 space-around 项目与项目之间的距离是两端间距的2倍。你可以理解为:margin-left、margn-right 设置了相同的值。
图2-4 space-between 与 space-around 的区别
图2-3完整代码:
<!DOCTYPE html>
<html>
<head>
<style>
body {
padding:0;
margin:0;
}
.flex-container-flex-start {
display: flex;
justify-content: flex-start;
}
.flex-container-flex-end {
display: flex;
justify-content: flex-end;
}
.flex-container-center {
display: flex;
justify-content: center;
}
.flex-container-space-between {
display: flex;
justify-content: space-between;
}
.flex-container-space-around {
display: flex;
justify-content: space-around;
}
.flex-item {
border:1px solid #fff;
height:60px;
width:120px;
text-align:center;
line-height:60px;
background: #f66;
color:white;
font-size:18px;
}
.flex-item.blue { background: #33f; }
.flex-item.gray { background: #666; }
.flex-item.purple { background: #f6f; }
.flex-item.brown { background: #9e5b03; }
.flex-item.circle {
border-radius: 10%;
}
h3 {
color: #666;
margin-top:10p;
border: 1px dashed #dcdcdc;
}
</style>
</head>
<body>
<h3>flex-start</h3>
<div class="flex-container-flex-start">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
</div>
<h3>flex-end</h3>
<div class="flex-container-flex-end">
<div class="flex-item gray">1</div>
<div class="flex-item gray">2</div>
<div class="flex-item gray">3</div>
<div class="flex-item gray">4</div>
<div class="flex-item gray">5</div>
<div class="flex-item gray">6</div>
</div>
<h3>center</h3>
<div class="flex-container-center">
<div class="flex-item blue">1</div>
<div class="flex-item blue">2</div>
<div class="flex-item blue">3</div>
<div class="flex-item blue">4</div>
<div class="flex-item blue">5</div>
<div class="flex-item blue">6</div>
</div>
<h3>space-between</h3>
<div class="flex-container-space-between">
<div class="flex-item purple">1</div>
<div class="flex-item purple">2</div>
<div class="flex-item purple">3</div>
<div class="flex-item purple">4</div>
<div class="flex-item purple">5</div>
<div class="flex-item purple">6</div>
</div>
<h3>space-around</h3>
<div class="flex-container-space-around">
<div class="flex-item brown">1</div>
<div class="flex-item brown">2</div>
<div class="flex-item brown">3</div>
<div class="flex-item brown">4</div>
<div class="flex-item brown">5</div>
<div class="flex-item brown">6</div>
</div>
</body>
</html>
2.1.5 align-items
align-items 属性,定义了项目在交叉轴上的对齐方式,有5个取值。
取值 | 说明 |
flex-start | 与交叉轴的起点对齐 |
flex-end |
与交叉轴的终点对齐 |
center | 在交叉轴上居中对齐 |
baseline | 以项目中第一行文字基线对齐 |
stretch | 在未设置高度情况下,将占满容器的高度 |
2.1.6 align-content
align-content 属性定义了多根主轴线在垂直方向上的对齐方式。
align-content 取值 | 说明 |
flex-start | 与交叉轴起点对齐 |
flex-end | 与交叉轴终点对齐 |
center | 在交叉轴上居中对齐 |
space-between | 与交叉轴两端对齐,轴线之间的间隔平均分布 |
space-around | 轴线之间的间隔平均分布,包括两端 |
stretch | 默认值,轴线占满交叉轴 |
2.2 项目属性
项目属性 | 默认值 | 说明 |
order | 0 | 定义了项目的排列顺序。 |
flex-grow | 0 | 扩大因子,定义了项目的放大比例 |
flex-shrink | 1 | 收缩因子,定义了项目的缩小比例 |
flex-basic | auto | flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。 |
flex | 0 1 auto | flex-grow、flex-shrink、flex-basis的缩写形式 |
align-self | auto | align-self 属性允许单个项目有与其他项目不一样的对齐方式, 也就是说改属性可以覆盖父容器设置的 align-items 属性。 |
在继续讲解这些项目属性之前,我们先来了解一个非常重要的概念 — 剩余空间。
图 2-5 剩余空间
为了解释剩余空间,下面给出一个示例。如图2-5所示,我们将父容器的宽度设置为 800px,容器中3个项目宽度分别为100px、200px、300px。那么,剩余空间就是:
200px = 800px - (100px + 200px + 300px)
简言之, flex-grow、flex-shrink 和 flex-basis 都是围绕如何分配剩余空间展开的。
2.2.1 order
order 属性,定义了项目的排列顺序,数值越小越靠前。可以为0,也可以为负值。order的默认值为 0
.item { order: <integer> }
图2-6 order 属性示例
图2-6 完整代码
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container {
display: flex;
margin-top:5px;
}
.item {
height:60px;
width:60px;
text-align:center;
line-height:60px;
background: #f66;
color:white;
font-size:18px;
border-radius: 100px;
}
.item.red {background: #f66;}
.item.blue { background: #66f; }
.item.gray { background: #666; }
.item.purple { background: #f6f; }
.item.brown { background: #9e5b03; }
h3 {
color: #666;
margin-top:10px;
border-bottom: 1px dashed #dcdcdc;
}
</style>
</head>
<body>
<h3>order</h3>
<div class="flex-container">
<div style="order:0" class="item red" >一</div>
<div style="order:1" class="item blue">二</div>
<div style="order:2" class="item gray" >三</div>
<div style="order:3" class="item purple">四</div>
<div style="order:4" class="item brown" >五</div>
</div>
<div class="flex-container">
<div style="order:4" class="item red" >一</div>
<div style="order:3" class="item blue">二</div>
<div style="order:2" class="item gray" >三</div>
<div style="order:1" class="item purple">四</div>
<div style="order:0" class="item brown" >五</div>
</div>
</body>
</html>
2.2.2 flex-grow
扩大因子,定义项目的放大比例 。
.item { flex-grow: <number> }
2.2.3 flex-shrink
收缩因子,定义了项目的缩小比例。
.item { flex-shrink: <number> }
图 2-7 flex-grow 与 flex-shrink 的使用
图2-7 完整代码
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container {
display: flex;
margin-top:1px;
}
.item {
height:60px;
width:60px;
text-align:center;
line-height:60px;
background: #f66;
color:white;
font-size:18px;
}
.item.red {background: #f66;}
.item.blue { background: #66f; }
.item.gray { background: #666; }
.item.purple { background: #f6f; }
.item.brown { background: #9e5b03; }
h3 {
color: #666;
margin-top:10px;
border-bottom: 1px dashed #dcdcdc;
}
</style>
</head>
<body>
<h3>flex-grow</h3>
<div class="flex-container">
<div style="flex-grow:0" class="item blue">0</div>
<div style="flex-grow:1" class="item red" >1</div>
<div style="flex-grow:2" class="item blue">2</div>
<div style="flex-grow:3" class="item red" >3</div>
<div style="flex-grow:4" class="item blue">4</div>
<div style="flex-grow:5" class="item red" >5</div>
</div>
<div class="flex-container">
<div style="flex-grow:0" class="item blue">0</div>
<div style="flex-grow:1" class="item red" >1</div>
<div style="flex-grow:0" class="item blue">0</div>
</div>
<h3>flex-shrink</h3>
<div class="flex-container" style="width:600px;border:1px dotted #dcdcdc;">
<div style="flex-shrink:0;width:100px;" class="item blue">100</div>
<div style="flex-shrink:1;width:100px;" class="item red" >100</div>
<div style="flex-shrink:2;width:100px;" class="item blue">100</div>
</div>
<div class="flex-container" style="width:600px;border:1px dotted #dcdcdc;">
<div style="flex-shrink:0;width:300px;" class="item blue">300</div>
<div style="flex-shrink:1;width:300px;" class="item red" >300</div>
<div style="flex-shrink:1;width:300px;" class="item blue">300</div>
</div>
<div class="flex-container" style="width:600px;border:1px dotted #dcdcdc;">
<div style="flex-shrink:0;width:300px;" class="item blue">300</div>
<div style="flex-shrink:1;width:300px;" class="item red" >300</div>
<div style="flex-shrink:5;width:300px;" class="item blue">300</div>
</div>
</body>
</html>
2.2.4 flex-basis
flex-basis 属性定义了在分配多余空间之前,项目占据主轴空间。默认值为:auto,即项目本来大小。
理解这段话的重点两个字就是 "之前"。
我们将3个 item 宽度分别设置为 100px、200px、300px,并且将第3个项目的 flex-basis 设置为 400px。可以看出,效果如下图第2行所示。
图2-8 加了 flex-basis 后的剩余空间
图2-8 完整代码:
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container {
display: flex;
width: 800px;
border: 1px solid red;
margin-top:5px;
}
.item {
width:60px;
text-align:center;
line-height:60px;
color:white;
font-size:18px;
border:1px solid #fff;
}
.item.red {background: #f66;}
.item.blue { background: #66f; }
.item.gray { background: #666; }
</style>
</head>
<body>
<div class="flex-container">
<div class="item red" style="width:100px">100px</div>
<div class="item blue" style="width:200px">200px</div>
<div class="item gray" style="width:300px;">300px</div>
</div>
<div class="flex-container">
<div class="item red" style="width:100px">100px</div>
<div class="item blue" style="width:200px">200px</div>
<div class="item gray" style="width:300px;flex-basis:400px;">300px/400px</div>
</div>
</body>
</html>
2.2.5 flex
flex 为 flex-grow、flex-shrink、flex-basis 的缩写形式。
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
默认值为: 0 1 auto
另外,改属性有两个快捷值:
flex: auto 相当于 flex: 1 1 auto
flex: none 相当于 flex: 0 0 auto
2.2.6 align-self
align-self 属性允许单个项目有与其他项目不一样的对齐方式。也就是说改属性可以覆盖父容器设置的 align-items 属性。
取值 | 说明 |
auto | 继承父元素的 align-items 属性 |
flex-start | 与交叉轴的起点对齐 |
flex-end |
与交叉轴的终点对齐 |
center | 在交叉轴上居中对齐 |
baseline | 以项目中第一行文字基线对齐 |
stretch | 在未设置高度情况下,将占满容器的高度 |
三、综合示例
为了加深对 Flex 布局的理解,下面给出2个综合性的例子。
3.1 倒序的瀑布流
(未完待续)
3.2 经典页面布局
(未完待续)
手工码字,虽然已经检查多遍,难免有不足之处,发现有错误之处,请多多指教。