Flexbox
Flexbox
Flexbox 简介
- 块布局 ― 为了呈现文档而设计出来的布局模式;
- 行内布局 ― 为了呈现文本而设计出来的布局模式;
- 表格布局 ― 为了用格子呈现
2D 数据而设计出来的布局模式; - 定位布局 ― 为了非常直接地定位元素而设计出来的布局模式,定位元素基本与其他元素毫无关。
而
-
main axis( 主轴) -
main dimension( 主轴方向) The main axis of a flex container is the primary axis along which flex items are laid out. It extends in the main dimension.
主轴是伸缩项目在伸缩容器里分布所遵循的主要轴线,在主轴方向上延伸。
-
main-start( 主轴起点)main-end( 主轴终点) The flex items are placed within the container starting on the main-start side and going toward the main-end side.
伸缩项目从容器的主轴起点开始放置,直到主轴终点。
-
main size( 主轴尺寸)main size property( 主轴尺寸属性) A flex item’s width or height, whichever is in the main dimension, is the item’s main size. The flex item’s main size property is either the width or height property, whichever is in the main dimension.
伸缩项目在主轴方向上的长或者宽是这个项目的主轴尺寸。一个伸缩项目的主轴属性是在主轴方向上的长或者宽属性。
-
-
cross axis( 交叉轴) -
cross dimension( 交叉轴方向) The axis perpendicular to the main axis is called the cross axis. It extends in the cross dimension.
和主轴垂直的轴叫做交叉轴,它在交叉轴方向上延伸。
-
cross-start( 交叉轴起点)cross-end( 交叉轴终点) Flex lines are filled with items and placed into the container starting on the cross-start side of the flex container and going toward the cross-end side.
包含伸缩元素的伸缩行从容器的交叉轴起点开始放置,直到交叉轴终点。
-
cross size( 交叉轴尺寸)cross size property( 交叉轴尺寸属性) The width or height of a flex item, whichever is in the cross dimension, is the item’s cross size. The cross size property is whichever of width or height that is in the cross dimension.
伸缩项目在交叉轴方向上的长或者宽是它的交叉轴尺寸。交叉轴尺寸属性则是在交叉轴方向上的长或者宽属性。
-
一般来说,
- 将元素切割到不同的行。首先会根据预测的元素尺寸将元素切分到不同的行。这主要是依赖
flex-basis 属性。 - 在每行中进行元素的缩放:对于每一行计算
flex 元素的最终尺寸 - 排列行与元素
具体而言,会有以下步骤:
- 首先根据每个元素的
flex-basis 属性计算每个元素的可能的尺寸 - 基于
flex-wrap 属性分析应该将元素分配到几行中 - 根据
flex-grow 与flex-shrink 属性计算元素的最终尺寸 - 根据
justify-content 属性计算元素在主轴上的排布 - 根据
align-items 、align-content、align-self 属性计算元素在交叉轴上的排布
Chrome | Safari | Firefox | Opera | IE | Android | iOS |
---|---|---|---|---|---|---|
20- (old)21+ (new) | 3.1+ (old)6.1+ (new) | 2-21 (old)22+ (new) | 12.1+ (new) | 10 (tweener)11+ (new) | 2.1+ (old)4.4+ (new) | 3.2+ (old)7.1+ (new) |
Polyfill
如果要在
<script src="flexibility.js"></script>
然后添加 -js-display: flex
在 display: flex
声明之前
.container {
-js-display: flex;
display: flex;
}
经过上文对于float
与position
的属性。不过,在移动端的实践中,很多的老版本浏览器,其中以微信内置的某自研浏览器为典型代表,还有一些即将退出历史舞台的
作为一个懒人,笔者希望能通过类似于
autoprefixer已经提供了面对部分老浏览器的
a {
display: flex;
}
会编译成
a {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex
}
笔者所使用的
var path = require("path");
var autoprefixer = require("autoprefixer");
module.exports = {
entry: path.resolve(__dirname, "demo.js"),
output: {
path: path.resolve(__dirname, ""),
publicPath: "",
filename: "demo.dist.js"
},
module: {
loaders: [
{
test: /\.jsx$/,
exclude: /(libs|node_modules)/,
loader: "babel?stage=0"
},
{
test: /\.js$/,
exclude: /(libs|node_modules)/,
loader: "babel?stage=0"
},
{
test: /\.(png|jpg|ttf|woff|svg|eot)$/,
loader: "url-loader?limit=8192"
}, // inline base64 URLs for <=8k images, direct URLs for the rest
{
test: /\.css$/,
loader: "style-loader!css-loader!postcss-loader"
},
{
test: /\.(scss|sass)$/,
loader: "style-loader!css-loader!postcss-loader!sass?sourceMap"
}
]
},
postcss: [autoprefixer({ browsers: ["last 10 versions", "> 1%"] })],
externals: {
jquery: "jQuery",
pageResponse: "pageResponse"
},
resolve: {
alias: {
libs: path.resolve(__dirname, "libs"),
nm: path.resolve(__dirname, "node_modules")
}
}
};
笔者在这里对几个常用的功能做了测试,确定了
.container {
-js-display: flex;
display: flex;
align-contents: stretch;
}
Flexibility 主要用来实现 Flexible Box Layout Module Level 1.
Flexbox 基本语法
容器属性
display: 属性定义
.container {
display: flex; /* or inline-flex */
}
该
flex-direction: 子元素方向
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
该属性用于定义主轴,即定义了子元素会以什么方向被放置到容器中。
flex-wrap: 行分割
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
一个

flex-flow: 混合了flex-direction 与flex-wrap
row nowrap
flex-flow: <‘flex-direction’> || <‘flex-wrap’>;
justify-content: 元素的主轴排列
该属性定义了元素在主轴上排列的方式,该属性会辅助分配余下的空白空间,在
.container {
justify-content: flex-start | flex-end | center | space-between | space-around;
}
flex-start
(default): 元素被放置在行首flex-end
: 元素向行尾聚集center
: 元素被放置在行中间space-between
: 元素被均衡分布,第一个元素被放置在行首,最后一个元素被放置在行尾。space-around
: 元素被均匀放置在行中,所有的空白空间被均衡分配,注意有些元素两边的空白不对等,那是因为左右两个元素的边空白叠加了。
align-items: 元素的交叉轴排列
.container {
align-items: flex-start | flex-end | center | baseline | stretch;
}
flex-start
: 元素被放置在交叉轴的首flex-end
: 元素向交叉轴尾聚集center
: 水平放置在交叉轴上baseline
: 基线对齐stretch
(default): 扩展以填充整个空间
元素属性
flex: 混合属性
0 1 auto
。
.item {
flex: none | [ < "flex-grow" > < "flex-shrink" >? || < "flex-basis" > ];
}
官方是推荐这种方式,毕竟它可以设置默认值。
flex-basis( 基准)
上文中已经提及,某个
- 由
width 、flex-basis 决定的基础尺寸 - 由
flex-grow 、flex-shrink 决定的不同容器尺寸情况下的缩放尺寸 - 由
max-* 、min-* 决定的尺寸的上限与下限
flex-basis: 0
withwidth: 45px
on each flex item results in the items having a0px
width.flex-basis: 10px
withwidth: 45px
on each flex item results in the items having a10px
width.flex-basis: auto
withwidth: 45px
on each flex item results in the items having a45px
width, and the items wrap because the sum of flex basis sizes exceeds the flex container’s width.flex-basis: content
withwidth: 45px
on each flex item should result in the flex items being sized exactly to their content, but this value is not supported as of the time I’m writing this.

flex-grow( 放大) & flex-shrink( 收缩)
flex-grow 的计算
首先我们做如下假设:
.flex-parent {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
flex-basis: auto;
width: 100px;
height: 50px;
}
.one {
flex-grow: 1;
width: 10px;
border: none; /* simplify calculations */
}
.two {
flex-grow: 2;
width: 20px;
border: none;
}
<div class="flex-parent blue">
<div class="one green">1</div><div class="two orange">2</div></div>
</div>
flex 父容器的排布为flex-direction: row
, 并且其尺寸为100px
- 然后有两个子元素
: - Item #1:
- 基础尺寸为
10px
(e.g. flex-basis: 10px
或者flex-basis: auto
加上width: 10px
) flex-grow
属性值为1
- 基础尺寸为
- Item #2:
- 基础尺寸为
20px
flex-grow
属性值为2
- 基础尺寸为
- Item #1:
那么,根据算法,计算过程为:
- 首先,计算该行的空白距离
100px
- 10px
- 20px
= 70px
- 确定每个元素的缩放比率,单元素的缩放比例为其
flex-grow 的值/ 总的flex-grow 值: - Item #1:
1/3
- Item #2:
2/3
- Item #1:
- 将空白距离按比例分配给各个子元素
. Item #1 新的尺寸: 10px + 1/3 * 70px = 33.3333px
Item #2 新的尺寸: 20px + 2/3 * 70px = 66.6666px
最终效果如下所示:

同样的,我们先做如下假设:
.flex-parent {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
width: 100px;
height: 50px;
}
.one {
flex-shrink: 1;
width: 100px;
border: none; /* simplify calculations */
}
.two {
flex-shrink: 2;
width: 100px;
border: none;
}
<div class="flex-parent blue">
<div class="one green">1</div><div class="two orange">2</div></div>
</div>
flex 父容器的排布为flex-direction: row
, 并且其尺寸为100px
- 然后有两个子元素
: - Item #1:
- 基础尺寸为
100px
(e.g. flex-basis: 100px
或者flex-basis: auto
加上width: 100px
) flex-shrink
属性值为1
- 基础尺寸为
- Item #2:
- 基础尺寸为
100px
flex-shrink
属性值为2
- 基础尺寸为
- Item #1:
那么,根据算法,计算过程为:
- 首先,计算该行的空白距离
100px
- 100px
- 100px
= -100px
- 确定每个元素的缩放比率,单元素的缩放比例为其
flex-shrink 的值/ 总的flex-shrink 值: - Item #1:
1/3
- Item #2:
2/3
- Item #1:
- 将空白距离按比例分配给各个子元素
. Item #1 新的尺寸: 100px - 1/3 * 100px = 66.6666px
Item #2 新的尺寸: 100px - 2/3 * 100px = 33.3333px

align-self
用于为每个元素设置单独的交叉轴排布方式:
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
注意,float、