CSS 布局 — 定位、flexbox、grid 与长度单位
CSS 布局 — 定位、flexbox、grid 与长度单位
这一章讲一件事:盒子(第 07 章盒模型)摆到哪、怎么排队。 三套机制各管一个层面:四种定位回答「这个盒子相对谁」;flexbox 回答「一排盒子怎么分一条轴」; grid 回答「整个页面怎么切成行和列」;外加老式的 float(认识一下,然后告别)和长度单位(所有尺寸的词汇表)。 学完这章,你就能把第 13 章那个真实应用的全部布局读明白了。
1. 先看现象:为什么「摆几个盒子」需要三套机制
想象你要排一个页面:顶上一条导航、中间左文右图、底部页脚。 「左文右图」用 flexbox 一行就够;但「整个页面五块区域各就各位」就要同时管行和列。 反过来,如果一个按钮组只需要「三个按钮均匀站开」,上 grid 就是杀鸡用牛刀。
这一章的三套机制不是三个世代的前后替代,而是三个不同问题的答案—— 虽然它们确实有年代顺序(定位 → float → flexbox → grid),各自还活着的原因是对应的问题永远存在。 原书给的分工口诀,今天仍然成立:一维用 flexbox,二维用 grid1。
2. 顶层全景:三套机制一张图
position(管“相对谁”): flexbox(管“一条轴怎么分”): grid(管“行×列一起切”):
static 正常排队(默认) display: flex 开工 display: grid 开工
relative 相对自己原来站的位置 flex-direction: row/column grid-template-columns: 1fr 1fr
absolute 移出队伍,相对最近的有 flex-wrap: wrap 窄了换行 grid-template-rows: auto…
定位的祖先 grid-column: 1 / 5(占 1 到 5 线)
fixed 钉在窗口上,滚动不挪 ← 元素可伸缩(grow/shrink) grid-row: 3 / 4(占第 3 行)
图说:定位回答“相对谁”,flex 回答“一条轴怎么分”,grid 回答“整张网怎么织”。3. 定位:四种 position,一个关键问题「移不移出队伍」
position 属性有四种常用值,书里逐个讲的2。理解它们的钥匙只有一个:
这个元素还占不占它原来的位置(文档流)?它相对谁量坐标?
static(静态)——默认,也是基准。 所有元素默认就是 static:按 HTML 书写顺序一个个排队,
此时 top/left 等偏移属性无效3。记住这条,因为后面三种全是「相对 static 那个本该在的位置」说话的。
relative(相对定位)—— visually 挪开,原位还占着。 元素相对自己 static 时本该在的位置偏移:
position: relative; top: 20px; = 「从你本来的位置向下挪 20 像素」4。
关键在书里点破的那半句:它原来的位置仍然被占着——别的元素不会挤进来。
所以 relative 最适合「把这个标签轻轻挪一点」这种微调,也最常当一个「锚」:它是 absolute 的参照物(见下)。
absolute(绝对定位)——移出队伍,相对最近的有定位祖先。 元素脱离文档流:
不占空间,其他元素当它不存在5。它的坐标相对谁?答案是「离它最近的那个非 static 祖先」——
如果一路上都没有,就相对整个页面。所以 absolute 的经典搭档是:
父元素设 position: relative(原地不动但获得「定位上下文」),子元素设 position: absolute; top: 0; right: 0;
(钉在父元素的右上角)。对话框的关闭按钮、图片角上的徽章,全是这个组合。
fixed(固定定位)——钉在窗口上。 也脱离文档流,但坐标相对浏览器窗口:
页面滚动它不动6。「回到顶部」按钮、吸顶导航,都是 fixed。
它和 absolute 的差别就是参照物:窗口 vs 祖先。
队伍: [A][B][C] ← B 设 relative、top:20px:A 和 C 不动,B 视觉上往下挪了
[A] [C] ← B 设 absolute:A、C 挤过来,占位消失,B 悬在原位置上方
窗口: [A][B]
滚滚滚…
[A][B] ← B 设 fixed:滚动不换位置
图说:relative 挪人不挪位;absolute/fixed 连位带人一起摘出队伍。4. flexbox:一维布局的发动机
flexbox 解决的问题:一组盒子沿一条轴(横排或竖列)怎么分配空间——
哪些撑大、哪些缩小、窄了怎么办。容器上写一句 display: flex,它的直接子元素立刻变成「弹性项」,
空间多了会分,空间少了会缩7。
.flex-container { display: flex; } ← 容器:宣布“我里面的孩子是弹性项”
┌──┐ ┌──┐ ┌──┐ ← 弹性项:沿主轴排队
│1 │ │2 │ │3 │
└──┘ └──┘ └──┘
图说:flex 管的是“这一排(或这一列)的伸缩与对齐”,管不了第二维。三个最常用调节项,书里都教了:
flex-wrap: wrap 是 flexbox 变成「半响应式」的开关:书里让你把浏览器窗口拉窄,
三个盒子装不下时自动换到下一行10——没写一行媒体查询,布局自己适应了。
当然这只是 flex 轴向上的自适应;真正全套的响应式是第 09 章。
flexbox 的边界要心里有数: 它只有一条轴。当布局需要「这个占两列、那个占一行」这种二维控制时, 就该 grid 上场。书里把话说得很直:flexbox 适合一维,grid 适合二维11。
判断(我们的,不是书里的): 书教 flexbox 只教到 direction 和 wrap, 没教
justify-content(主轴上怎么分布:居中/两端/均匀)和align-items(交叉轴上怎么对齐)—— 而这两个才是 flexbox 日常用得最多的调节项,第 13 章的项目里其实偷偷用了 (justify-content: space-between把任务文字和按钮分居左右)。 读者需要自己顺着「分布/对齐」这个缺口补一刀。这是本书的选择性简化,不算错,但要知道缺口在哪。 如果错,会错在: 如果哪天 CSS 出了真正一统的布局机制,flex/grid 的分工口诀会失效—— 但截至 2026 年,这句口诀仍是这一行面试题的标准答案。
5. grid:二维布局,整页一「网」打尽
grid 解决的问题:同时定义行和列,让元素像棋子一样摆进格子里。
容器写 display: grid,然后用两条属性织网、两条属性摆子12。
织网:
body {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr; /* 四列,等宽 */
grid-template-rows: auto auto auto auto; /* 四行,高度随内容 */
}fr 是 grid 的招牌单位——fractional unit(分数单位):把容器里剩的空间按份分,
1fr 1fr 1fr 1fr 就是四等份13。auto 则是「这行多高随内容定」。注意这和第 07 章「width: 400px」
的思路本质不同:px 是写死的,fr 是按比例分剩下的——窗口变宽每列一起变宽。
摆子:每个子元素用「起止线」报位置,语法是 起 / 止(网格线从 1 开始数):
header { grid-column: 1 / 5; grid-row: 1 / 2; } /* 占满 4 列,在第 1 行 */
main { grid-column: 1 / 4; grid-row: 3 / 4; } /* 占前 3 列 */
aside { grid-column: 4 / 5; grid-row: 3 / 4; } /* 占最后 1 列 */
footer { grid-column: 1 / 5; grid-row: 4 / 5; } /* 第 4 行,通栏 */ 线1 线2 线3 线4 线5
┌────────────────────────────────────────────────┐ 线1
│ header (1/5, 1/2) │
├────────────────────────────────────────────────┤ 线2
│ nav (1/5, 2/3) │
├───────────────────────────────┬────────────────┤ 线3
│ main (1/4) │ aside (4/5) │
├───────────────────────────────┴────────────────┤ 线4
│ footer (1/5, 4/5) │
└────────────────────────────────────────────────┘ 线5
图说:列线竖着数 1–5,行线横着数 1–5;“1 / 5” = 从 1 号线到 5 号线,恰好通栏。这就是第 09 章响应式改造的底子:到时候不需要重写这个结构,只要在媒体查询里重排这些起止线, 同一批元素就能在手机上单列堆叠。grid 结构 + 媒体查询重排,是 2026 年响应式的主流打法之一。
6. float 与 clear:遗产课
在 flexbox/grid 之前(大约 2005–2015),网页布局靠的是一对原始工具:
float 最初的设计用途是让文字绕图排版(图片浮在左/右,文字围过去)14;
后来被强行征用做整页布局——那段历史催生过无数「清除浮动」的邪派武功。
clear 是配套的刹车:阻止元素绕到浮动元素旁边,把它强制压到浮动元素下方15。
书里给的结论可以直接当这一行的公论:float 和 clear 如今很少用于布局,
flexbox 和 grid 更好,尽量别用 float 做布局16。它剩下的正当用途只有一个:文章里的图文混排。
读老代码时会大量遇到 float: left + 各种 clearfix——认识它,是为了看懂过去,不是为了用它。
7. 长度单位:尺寸的词汇表
所有 width、height、padding、margin 都要带单位。书里把单位分成绝对、相对两家17:
| 类别 | 单位 | 含义 | 典型场景 |
|---|---|---|---|
| 绝对 | px | 像素,屏幕上的点 | 边框、小图标 |
| 绝对 | pt | 磅,印刷单位(1pt ≈ 1.33px) | 字号的历史习惯 |
| 绝对 | in / mm | 英寸 / 毫米 | 打印样式表 |
| 相对 | % | 父元素对应尺寸的几成 | 宽度、高度的一半份额 |
| 相对 | em | 当前元素字号的几倍 | 间距随字号走 |
| 相对 | fr | 剩余空间的几份(grid/flex 语境) | 网格列宽 |
em 值得单独看一眼,书里给了算式:字号 12pt 时,2em = 24pt,1.5em = 18pt18——
em 的参照物是「当前字号」,所以用 em 写的间距会跟着字号缩放,这就是它适合做「内边距跟着文字走」的原因。
(它的亲戚 rem——相对根元素字号——本书没提,日后见到知道是「永远相对页面默认字号」的 em 就行,④ 类补充。)
为什么单位分两家的根本理由是响应式(第 09 章的入场券): 绝对单位不知道屏幕变了, 相对单位知道。「用 % 和 fr 写骨架,用 px 写细节」是这一行的默认值。
8. 主线例子:一个页面骨架的三种摆法
这一章的主线例子,是书里那个四列四行的餐厅页面骨架(header/nav/main/aside/footer), 同一个目标用三套机制各摆一遍(尺寸数字沿用书中例子,便于对照):
目标:header 通栏、nav 通栏、main 占 3 列、aside 占 1 列、footer 通栏
摆法一(position 时代——书里没这么教,2010 年代实况):
aside { float: right; width: 25%; }
main { margin-right: 25%; } ← 手动给 aside 让位;浮动溢出还要 clear 收拾
摆法二(flexbox——只能一维,要嵌套):
body { display: flex; flex-direction: column; } ← 先竖排五大块
中间再包一层 div { display: flex; } ← 再横排 main 和 aside
← 为了布局多造了一层无意义标签,是 flexbox 时代的典型代价
摆法三(grid——书里教的做法,二维一次到位):
body { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; }
header { grid-column: 1 / 5; } main { grid-column: 1 / 4; }
aside { grid-column: 4 / 5; } footer { grid-column: 1 / 5; }
← 结构标签一个没多加,行列各归各位
图说:同一个骨架,float 要靠“让位”骗、flex 要靠嵌套凑、grid 直接说——这就是三代工具的差距。这个对照是本章的落点: 不是「grid 最新所以最好」,而是表达力的差别—— grid 让你用结构本身的语言(行、列、占几格)描述布局,而不是借别的机制打比方。 这也是为什么今天的新项目默认 grid/flex,float 只剩博物馆。
9. 作者的判断与证据
书内作为事实给出的: 四种 position 的语义(尤其 relative 占原位的细节、absolute 脱流)45、 flex 与 grid 的一维/二维分工11、fr 的含义13、float 的原始用途与退场1416、单位两家分类17。
需要以标准为准修正原书的地方: 书里多处写 flex-direction: rows/columns(复数),
CSS 规范的值是单数 row/column8;引用时以单数为准,书中显然是笔误。
另外 grid 例子的 HTML 用了 <header>、<nav>、<main>、<aside>、<footer> 这组语义化标签——
书里直接用但没解释,我们补上:这组标签是「页面区域的身份声明」,和 <strong> 一个道理,
对搜索引擎和读屏软件说「这是导航、这是正文」。第 13 章会再用一次。
10. 边界与局限
- flexbox 教得浅:
justify-content/align-items/gap这三个日常调节项没教(第 13 章的项目代码里却出现了)——缺口要自补。 - grid 没教
grid-template-areas:那是比「起止线」更好读的网格摆法(给每个区域起名字再摆名字),入门之外的第一课。 - 定位没教
z-index与层叠上下文:多个 absolute/fixed 元素重叠时谁压谁,是个有独立深度的话题,本书完全没碰。 rem、vw/vh没提;min-width/max-width要到第 09、13 章才实际出现。
11. 可带走的
全章主线例子,一行写完: 同一个五区骨架,float 靠让位、flex 靠嵌套、grid 靠 grid-column: 起/止 一句话——表达力就是三代的差距。
- position 的钥匙是「移不移出队伍、相对谁量坐标」:static 默认、relative 挪位不占队、absolute 出队相对非 static 祖先、fixed 钉窗口2;
- absolute 的经典搭档:父
relative+ 子absolute(关闭按钮、角标); - flexbox = 一条轴的分配;两个开关:
flex-direction(横/竖)、flex-wrap(换行)89; - grid = 行列一起织:
display: grid+grid-template-columns/rows织网 +grid-column/row: 起/止摆子; fr按份分剩余空间,auto随内容——相对单位是响应式的入场券;- float 只做图文混排,布局别碰;clear 是配套的刹车16;
- 单位两家:绝对(px/pt)写细节,相对(%/em/fr)写骨架;
- 一维 flex、二维 grid——这句口诀 2026 年仍是标准答案11。
12. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| static 默认与偏移无效 | CSS for Layouts | text/14-fm-introduction.txt:31(搜「default positioning of all elements」) |
| relative 相对原位、原位仍占 | CSS for Layouts | text/14-fm-introduction.txt:35(搜「positioned relatively」) |
| absolute 脱离文档流 | CSS for Layouts | text/14-fm-introduction.txt:43(搜「positioned as absolute」) |
| fixed 相对浏览器窗口 | CSS for Layouts | text/14-fm-introduction.txt:47(搜「fixed positioning is removed」) |
| flex 容器与方向 | CSS for Layouts | text/14-fm-introduction.txt:61(搜「display: flex」) · text/14-fm-introduction.txt:75(搜「flex-direction」) |
| flex 换行 | CSS for Layouts | text/14-fm-introduction.txt:107(搜「flex-wrap」) · text/14-fm-introduction.txt:119(搜「make it smaller」) |
| grid 织网与 fr | CSS for Layouts | text/14-fm-introduction.txt:145(搜「fractional unit」) · text/14-fm-introduction.txt:153(搜「grid-template-columns: 1fr」) |
| grid 摆子(grid-column/row) | CSS for Layouts | text/14-fm-introduction.txt:163(搜「grid-column: 1 / 5」) |
| float 的本来用途 | CSS for Layouts | text/14-fm-introduction.txt:325(搜「float property was originally」) |
| clear 的作用 | CSS for Layouts | text/14-fm-introduction.txt:337(搜「clear property prevents」) |
| float 退场建议 | CSS for Layouts | text/14-fm-introduction.txt:339(搜「much better to use flexbox or grid」) |
| 单位两家分类 | CSS for Layouts | text/14-fm-introduction.txt:345(搜「same size regardless」) · text/14-fm-introduction.txt:385(搜「fractional unit」) |
| 章末:一维/二维分工 | CSS for Layouts | text/14-fm-introduction.txt:415(搜「flexbox is best suited」) |
Footnotes
-
出处:「CSS for Layouts」第 415 段(
text/14-fm-introduction.txt:415,搜「flexbox is best suited」)。原文:「Flexbox is best suited for one-dimensional layouts, while CSS grid is more effective for two-dimensional layouts involving both rows and columns.」 ↩ -
出处:「CSS for Layouts」第 29 段(
text/14-fm-introduction.txt:29,搜「four commonly used values」)。原文列出 position 的四个常用值:static、relative、absolute、fixed。 ↩ ↩2 -
出处:「CSS for Layouts」第 31 段(
text/14-fm-introduction.txt:31,搜「default positioning of all elements」)。原文:「Static-positioned elements are not affected by the top, bottom, left, and right properties.」 ↩ -
出处:「CSS for Layouts」第 35 段(
text/14-fm-introduction.txt:35,搜「positioned relatively」)。原文:「Setting the top, right, bottom, and left properties will move the element visually away from its original position.」 ↩ ↩2 -
出处:「CSS for Layouts」第 43 段(
text/14-fm-introduction.txt:43,搜「positioned as absolute」)。原文:「it is removed from the normal document flow... other elements will ignore its presence.」 ↩ ↩2 -
出处:「CSS for Layouts」第 47 段(
text/14-fm-introduction.txt:47,搜「fixed positioning is removed」)。原文:「positioned relative to the browser window. It stays fixed in its position even when the page is scrolled.」 ↩ -
出处:「CSS for Layouts」第 53–65 段(
text/14-fm-introduction.txt:53,搜「layout model」;:61,搜「display: flex」)。原文:「The flex property in the display element specifies how a flex item will grow or shrink to fit the space available in its container.」 ↩ -
出处:「CSS for Layouts」第 75–95 段(
text/14-fm-introduction.txt:75,搜「flex-direction」)。原文意图为 row/column;书中写作 rows/columns 是笔误,以 CSS 标准(单数)为准。 ↩ ↩2 ↩3 -
出处:「CSS for Layouts」第 99–109 段(
text/14-fm-introduction.txt:107,搜「flex-wrap」)。原文:「the items will wrap to the next row if the screen size is smaller.」 ↩ ↩2 -
出处:「CSS for Layouts」第 119 段(
text/14-fm-introduction.txt:119,搜「make it smaller」)。原文:「Now, when we resize the browser window, for example, make it smaller, you can see the flexbox items wrap.」 ↩ -
出处:「CSS for Layouts」第 415 段(
text/14-fm-introduction.txt:415,搜「flexbox is best suited」)。 ↩ ↩2 ↩3 -
出处:「CSS for Layouts」第 125–153 段(
text/14-fm-introduction.txt:125,搜「layout system」;:143,搜「grid container with four columns」;:153,搜「grid-template-rows: auto auto auto auto」)。 ↩ -
出处:「CSS for Layouts」第 145 段(
text/14-fm-introduction.txt:145,搜「fractional unit」)。原文:「The unit fr stands for fractional unit and is used to allocate a proportion of the available space within the grid container.」 ↩ ↩2 -
出处:「CSS for Layouts」第 325 段(
text/14-fm-introduction.txt:325,搜「float property was originally」)。原文:「The float property was originally used to wrap text around images, although it is used less frequently today thanks to flexbox and grid.」 ↩ ↩2 -
出处:「CSS for Layouts」第 337 段(
text/14-fm-introduction.txt:337,搜「clear property prevents」)。 ↩ -
出处:「CSS for Layouts」第 339 段(
text/14-fm-introduction.txt:339,搜「much better to use flexbox or grid」)。原文:「It is much better to use flexbox or grid.」 ↩ ↩2 ↩3 -
出处:「CSS for Layouts」第 341–385 段(
text/14-fm-introduction.txt:345,搜「same size regardless」)。原文:「Units that are absolute are the same size regardless of the parent element or window size.」 ↩ ↩2 -
出处:「CSS for Layouts」第 377 段(
text/14-fm-introduction.txt:377,搜「12 x 2」)。原文:「If a font is set to 12pt, each em unit would be 12pt, so 2em would be 12 x 2, which is 24pt.」 ↩