现在(2019)主流的 CSS 框架都使用的 Flexbox。比如 Bulma 的 column 系统。
Core
Flexbox 是在一个维度上排列项目的排版方式。Grid 提供了在两个维度上的排版方式。
Flexbox 的模型大概如图,由一个 容器(box / container) 包含着若干个 项目(item):
它有一个主轴(main axis,在上图中是 row
),表明它是横向排列项目还是纵向,以及项目默认排列方向,比如从左向右还是从右往左。还有一个交叉轴(cross axis),与主轴成交叉。
Flexbox 有几个核心问题要解决:
- 一个盒子的轴(axis)是什么。轴代表了 box 中项目的排列方向,可横着排也可竖着排(
flex-direction
,flex-wrap
以及flex-flow
shoutcut) - 项目占用的空间是多少;如果盒子剩余空间过多或者不够,项目的占用空间应该怎样调整、是否要换行(
flex-basis
,flex-grow
以及flex-shrink
) - 项目在主轴上应该怎样分布,是都挤在左边还是往两边散开(
justify-content
);在交叉轴上应该怎样分布(align-items
,align-self
) - 当发生换行并且存在多行时,各行处在容器的什么位置上(
align-content
)
容器的 display
需要设置成 flex
。
上面提到的 CSS 属性中:
- 用在容器上:
flex-direction
,flex-wrap
,flex-flow
- 用在项目上:
flex-basis
,flex-grow
,flex-shrink
,align-self
- 同时可用:
justify-content
:用在容器上表示项目的排列;用在项目上时表示项目内容的排列align-items
:同justify-content
,区别在于justify-content
处理 main axis,而align-items
处理 cross axis
flex
是这三者的 short hand:flex-grow
, flex-shrink
, flex-basis
。
flex-basis
这篇 文章 给出了很好的解答。
简单来说,一个 flex item 在 grow / shrink 之前的宽度/高度判定是这样的:
- 如果设置了
flex-basis
,优先用它,否则: - 如果设置了
width
或者height
,优先用它,否则: - 根据其内容多少来判定
不管用哪个属性,它们都遵循 max-width
/ min-width
(或其 height
版本)所带来的约束。
常见用法
Tailwind CSS 描述了一些 常见用法。
Bulma 分栏系统实现
对于未指定宽度的栏,Bulma 默认都使用这样的属性,让它们自动分配大小:
flex-basis: 0;
flex-grow: 1;
flex-shrink: 1;
当有一些栏指定了宽度比例(比如 is-four-fifths
)时,Bulma 采用百分比(如 80%)作为其宽度值并置 flex: none
(即 flex: 0 0 auto
)使其不会自动扩缩。
为了让不同栏之间的距离合理,应该:
- 使用
border-box
的box-sizing
使宽度计算中包含border
及padding
- 栏之间的空白应该使用
padding
而不是margin
,因为margin
不包含在border-box
中
Resources
- A Complete Guide to Flexbox: 简单易懂地讲解 flexbox
- Flexbox - CSS Reference: 快速理解 Flexbox 中各属性及其值的作用