第 1 课:让盒子排成一行的那行声明
本课目标:
- 说出
display: flex对容器及其子元素做了什么。- 辨认哪些元素会变成 flex item(哪些不会)。
- 预测 flex item 默认沿主轴排成一行。
先修条件:你会写一个带 class 的
<div>并设置一个 CSS 属性 | 下一篇 02 >>
没有 Flexbox 时,盒子只会竖着堆。为什么?
往页面上放三个 <div>,它们会竖直堆叠,每个独占一行。这是正常的块级布局,而多年以来,把它们并排放的办法只有浮动和 inline-block 这类到处漏间距 bug 的手段。如果 Flexbox 在你眼里是一堆“粘贴上去再祈祷”的属性,通常是因为没人给你讲它做的第一件事,也就是其他所有属性都依赖的那件事。这一课只讲这第一件事:一条声明,把竖着的堆变成横着的一行。掌握这一点,课程剩下的部分不过是“哪个方向、哪条轴”。
讲解
起步的全部诀窍在这里。你选定容器(包住那些盒子的元素),在它身上设置一个属性:display: flex。该容器的直接子元素随即成为 flex item1。这就是整个开关。
你这么做的那一刻,子元素不再堆叠,而是从左到右排成一行。它们现在沿着容器的主轴排列,主轴默认是水平方向1。你完全没有碰子元素,你改的是父元素,而父元素现在把它的子元素按一条 flex 行摆放。
有一个细节常常绊倒人:只有直接子元素会变成 flex item。如果 flex 容器里放着一张卡片,而卡片内部又有一个标题和一个段落,那么卡片是 flex item,但标题和段落不是。它们属于卡片,比这个容器能安排的层级深了一层2。
“只往下一层”这件事是特性而不是限制,因为容器可以嵌套。给那张卡片自己也设上 display: flex,它就成了一个嵌套 flex 容器:同一时刻既是外层行的 flex item,又是自己标题和段落的 flex 容器。真实布局都是这么搭的——外层容器摆卡片,每张卡片摆自己的内容。嵌套不需要任何特殊写法,你只是在下一层再写一次 display: flex。
还有一个同族的值。display: inline-flex 同样会造出一个 flex 容器,对子元素的作用完全一样;区别只在容器自己怎么待在页面里——flex 让它成为块级 flex 容器,inline-flex 让它成为行内的1。如果你的一行 item 内部排得没问题,却死活不肯和旁边的文字并排,要看的就是外层这个值。
下面的编辑器是真的。三个盒子正在堆叠。给 .row 加上那条把它变成 flex 容器的声明。
当状态点变成完成时,盒子就在主轴上了。注意你只给 .row 加了 display: flex,没有设宽度、没有浮动、没有对盒子本身做任何事。这就是整门课建立在其上的转变:你通过配置父元素来安排子元素。
完整示例(跟着做)
假设你有一个页头,里面是 logo 和导航,它们正在堆叠:
一步一步说清为什么这样有效。.bar 是容器,所以 display: flex 设在它身上。它的直接子元素是 .logo 和 .links,正好是两个 flex item。设了 display: flex 之后,这两个 item 沿主轴排列,主轴默认水平,所以 logo 和导航在同一行上,logo 在左。你没有给任何子元素设置尺寸,是 flex 行把它们摆好的。
你来试试(填空示例)
你有一个工具栏,三个按钮应该排成一行,但它们正在堆叠。补上缺的那一行:
答案:缺的那一行是 display: flex;。三个 <button> 元素是 .toolbar 的直接子元素,所以它们变成 flex item,沿主轴排成一行。按钮本身什么都不用改。
这一行已经替你定下了什么
display: flex 不是一个行为,它一次性打开了一整套初始值,而后面每一课其实都只是在覆盖其中某一个。现在把这份清单读一遍是值得的,因为你后面会遇到的每一个“意外”,都是这些默认值在老实干活1:
- item 排成一行,因为
flex-direction的起点是row。 - item 从主轴的起始边开始排,而不是从中间开始。
- item 在主轴方向上不拉伸、但可以收缩,因为
flex-grow起点是0,flex-shrink起点是1。 - item 会拉伸填满交叉轴,因为
align-items的起点是stretch——这就是为什么三张内容不一样多的卡片,你什么都没写它们却一样高。 - 每个 item 在主轴上的尺寸来自它自己的 width,没有 width 就来自内容,因为
flex-basis起点是auto。 - 所有东西都留在一行上,放不下就溢出,因为
flex-wrap起点是nowrap。
Flexbox 是一维布局模型:它一次只沿一条轴摆放 item,要么一行要么一列,这正是它和 CSS Grid 的分界——Grid 同时控制行和列这两个维度1。当你发现自己想让 item 既在列方向对齐又在行方向对齐时,那就是信号:你已经走出 Flexbox 的职责范围了。
小结 + 下节课预告
容器上的 display: flex 把它的直接子元素变成 flex item,并沿主轴摆放,主轴默认水平。你通过配置父元素来安排子元素,而 flex 只往下作用一层。下一课我们给两条轴命名,因为一旦有了两个方向,每条轴各有一个对齐属性,justify-content 和 align-items 也就终于讲得通了。
Footnotes
-
MDN: Basic concepts of flexbox — https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Flexible_box_layout/Basic_concepts ↩ ↩2 ↩3 ↩4 ↩5
-
CSS-Tricks: A Complete Guide to Flexbox — https://css-tricks.com/snippets/css/a-guide-to-flexbox/ ↩
练习
在你的 flex 行里嵌一张卡片:给其中一个子 div 加上自己的 <h3> 和 <p>。刷新并观察。<h3> 和 <p> 是被这条 flex 行安排的吗?
第 2 级(进阶)我的笔记
记下想法、痛点、没懂的地方。只写进这门课的附录,正课文件不动。