Introduction
Flexbox 是一种非常强大的布局模式。当我们真正了解了它的工作原理后,就能构建自动响应的动态布局,并根据需要重新排列。
例如,看看这个:
本演示深受 Adam Argyle 令人难以置信的 codepen “4 layouts for the price of 1” 的启发。它不使用媒体/容器查询。 它没有设置任何的折行点,而是利用流体原理创建了一个流畅的布局。
下面是相关的 CSS:
css
我记得自己在观看这样的演示时,完全摸不着头脑。我知道 Flexbox 的基本原理,但这似乎是绝对的魔法!
在本篇博文中,我希望完善您的 Flexbox 心智模型。 我们将通过了解这些属性中的每一个,建立对 Flexbox 算法工作原理的直观认识。无论你是 CSS 初学者,还是使用 Flexbox 多年的老手,我打赌你都能学到不少东西!
我们开始吧
Link to this headingFlexbox 简介
CSS 包含多种不同的布局算法,正式名称为 “布局模式”。每种布局模式都是 CSS 中的一种子语言。默认的布局模式是流式布局,但我们可以通过更改父容器上的 display
属性,选择使用 Flexbox:
当我们将 display
设置为 flex
时,我们会创建一个 “flex 模式上下文”。这意味着,默认情况下,所有子元素都将按照 Flexbox 布局算法进行摆放。
每种布局算法都是为解决特定问题而设计的。 默认的“流式”布局旨在创建数字文档;它基本上是微软 Word 的布局算法。标题和段落以块的形式垂直堆叠,而文本、链接和图片等内容则位于这些块中,并不显眼。
那么,Flexbox 能解决什么问题呢? Flexbox 就是在一行或一列中排列一组元素,并赋予我们对这些元素的分布和对齐方式的极大控制权。顾名思义,Flexbox 就是灵活性。我们可以控制元素的拉伸或收缩,以及额外空间的分配等等。
Link to this headingFlex 排列方向
如前所述,Flexbox 就是要控制元素在一行或一列中的分布。默认情况下,元素将并排堆叠在一行中,但我们可以使用 flex-direction
属性翻转到一列中:
使用 flex-direction: row
时,主轴是水平的,从左到右。当我们切换到 flex-direction: column
时,主轴会从上到下垂直排布。
在 Flexbox 中,一切都基于主轴(Primary axis)。 算法并不关心垂直/水平,甚至行/列。所有规则都是围绕主轴和垂直于主轴的纵轴(Cross axis)来构建的。
这很酷。 当我们掌握了 Flexbox 的规则后,就可以从水平布局无缝切换到垂直布局。所有规则都会自动调整。这一功能是 Flexbox 布局模式所独有的。
默认情况下,子元素们将根据以下两条规则进行排列:
- 主轴方向(Primary axis): 子元素将集中在容器的起始位置。
- 纵轴方向(Cross axis): 子元素将伸展开来,填满整个容器。
下面是这些规则的快速可视化示意图:
在 Flexbox 中,我们先要设定主轴是横向还是纵向。这是所有 Flexbox 布局计算的根基。
我们可以使用 justify-content
属性更改子元素沿主轴的分布方式:
说到主轴,它通常不是针对对齐某一个子元素。相反,它是针对 整个组的排列。
我们可以将所有元素集中在一个特定的位置(使用 flex-start
, center
,和 flex-end
),也可以将它们分散开来(使用 space-between
, space-around
, 和 space-evenly
)。
纵轴的情况则有些不同。 我们使用 align-items
属性:
有趣的是,对于 align-items
,我们有一些与 justify-content
相同的选项,但并不完全重合。
为什么它们不共享相同的选项呢?我们很快就会揭开这个谜团,但首先,我需要再分享一个对齐属性:align-self
。
与 justify-content
和 align-items
不同, align-self
适用于子元素,而不是容器。它允许我们改变特定子元素沿纵轴的对齐方式:
align-self
的值与 align-items
完全相同。事实上,它们改变的是完全相同的东西。align-items
is 是一种语法糖,是一种方便的速记法,可以自动一次性设置所有子元素的对齐方式。
没有 justify-self
。要理解为什么没有,我们需要深入研究 Flexbox 算法。
Link to this headingContent vs. items
因此,根据我们目前所学到的知识,Flexbox 似乎很武断。为什么是 justify-content
和 align-items
,而不是 justify-items
, 或 align-content
?
那么,为什么有 align-self
,却没有 justify-self
呢??
这些问题涉及 Flexbox 最重要也是最容易被误解的一点。 为了帮助我解释,我想用一个比喻来说明。
在 Flexbox 中,子元素沿主轴分布。默认情况下,它们是并排整齐排列的。我可以画一条水平直线,将所有子元素串起来,就像 烤肉串?一样?
但纵轴是不同的。一条垂直直线只会与其中一个子元素相交。
它不像烤肉串,更像一排 烤肠?:
这里有一个显著的区别。有了烤肠,每件物品都可以沿着自己的签子移动,而不会影响其他任何物品:
相比之下,由于我们的主轴将每个子元素串成一线,单个元素无法在不撞到兄弟姐妹的情况下沿着主轴移动 试着左右拖动中间部分:
这就是主轴/纵轴之间的根本区别。 当我们在纵轴上讨论排列时,每个子元素都可以随心所欲。但在主轴上,我们只能考虑如何 分组排布。
这就是为什么没有 justify-self
的原因。 如果中间的元素设置成 justify-self: flex-start
会怎样? 已经有元素在那里了!
有了这些背景,让我们来给我们一直在谈论的这四个术语下一个正确的定义:
justify
— 沿主轴排列。align
— 沿纵轴排列。content
— 一组可以排列摆放的“东西”items
— 一个可以单独摆放的东西
因此,我们使用 justify-content
来控制组沿主轴的分布,使用 align-items
来沿纵轴单独定位每个项目。这就是我们使用 Flexbox 管理布局的两个主要属性。
没有 justify-items
的原因与没有 justify-self
的原因相同;当涉及主轴时,我们必须将子元素视为一个组,视为可以排列的内容。
那么 align-content
呢?实际上,Flexbox 中确实存在对齐内容!我们稍后会在讨论 flex-wrap
属性时介绍它。
让我们来谈谈我对 Flexbox 的一个最直观的认识。
假设我有以下 CSS:
css
一个理智的人看到这里可能会说:“好吧,我们将得到一个 2000 像素宽的子元素”。 但事实会一定如此吗?
让我们来测试一下:
Code Playground
Result