学 CSS 布局时,几乎所有概念最后都会回到一个词:文档流。
block、inline、position、float、absolute、flex、grid……
你如果不理解“普通文档流”,后面很多现象都会觉得像玄学。
这篇文章就把它讲透。
目录
- 一、先说结论:文档流到底是什么
- 二、为什么浏览器需要文档流
- 三、普通文档流里元素是怎么排的
- 四、块级元素和行内元素在文档流中的表现
- 五、什么叫“脱离文档流”
- 六、哪些东西会脱离普通文档流
- 七、为什么理解文档流这么重要
- 八、几个最容易混淆的点
- 九、一张表总结
- 十、结论
一、先说结论:文档流到底是什么
你可以先记住一句最重要的话:
普通文档流,就是浏览器默认摆放元素的一套基础规则。
当你什么都不特别设置时,页面里的元素会按照 HTML 的先后顺序,一个一个排下去。
浏览器会根据元素类型决定怎么放:
- 块级元素:通常从上到下,一个接一个
- 行内元素:通常在一行里,从左到右,放不下再换行
这套“默认怎么排”的规则,就是普通文档流。
二、为什么浏览器需要文档流
浏览器拿到 HTML 后,不可能把所有元素胡乱堆在一起,它必须有一套基础排版机制。
比如:
<h1>标题</h1>
<p>第一段文字</p>
<p>第二段文字</p>
浏览器天然知道应该这样排:
- 标题先出来
- 第一段在标题下面
- 第二段在第一段下面
这不是巧合,而是因为这些元素都在普通文档流里。
所以你可以把普通文档流理解成:
浏览器的默认排版秩序。
没有它,页面就没法自动形成结构。
三、普通文档流里元素是怎么排的
1. 按源码顺序排
文档流最基础的规则就是:
谁先写,谁先排。
例如:
<div>A</div>
<div>B</div>
<div>C</div>
默认情况下,页面就会按 A → B → C 的顺序排列。
2. 块级元素通常竖着排
例如:
<div>块1</div>
<div>块2</div>
<div>块3</div>
默认表现通常是:
- 块1 一行
- 块2 下一行
- 块3 再下一行
因为块级元素在普通文档流中通常会独占一行。
3. 行内元素通常横着排
例如:
<span>A</span>
<span>B</span>
<span>C</span>
默认表现通常是:
- A、B、C 在同一行
- 放不下再自动换行
因为行内元素在普通文档流中通常按文本流规则排列。
四、块级元素和行内元素在文档流中的表现
1. 块级元素
默认特点:
- 独占一行
- 从上到下排列
- 宽度通常尽量撑满父容器
常见例子:
divph1 ~ h6sectionarticle
2. 行内元素
默认特点:
- 不独占一行
- 在一行里从左到右排列
- 像文字一样参与排版
常见例子:
spanastrongem
3. 所以文档流并不是一种“单一排列方式”
它实际上同时包含了两套默认规则:
- 块级格式的默认排法
- 行内格式的默认排法
这也是为什么你看到 div 和 span 的默认表现完全不同。
五、什么叫“脱离文档流”
这是文档流里最核心的进阶概念。
所谓“脱离文档流”,可以先这样理解:
这个元素不再按照浏览器默认的那套排版秩序占位置了。
也就是说,它不再老老实实地按源码顺序、按块级/行内规则排在原来的位置里。
最直接的结果通常是:
- 它原本的位置可能不再被它占着
- 后面的元素会像它不存在一样继续排
- 它会用另一套规则决定自己放哪儿
六、哪些东西会脱离普通文档流
1. position: absolute
绝对定位元素会脱离普通文档流。
例如:
.box {
position: absolute;
top: 0;
left: 0;
}
效果通常是:
.box不再占据原来位置- 后面的元素会顶上来
.box自己按定位规则放到别处
2. position: fixed
固定定位也会脱离普通文档流。
.box {
position: fixed;
right: 20px;
bottom: 20px;
}
它直接相对视口放置,不再按普通流排。
3. float
浮动元素比较特殊。
它不是像 absolute 那样完全独立,但也不再像普通块级元素那样老老实实占位。
所以通常也会被认为“脱离普通文档流的常规排列影响”。
七、为什么理解文档流这么重要
因为你在 CSS 里遇到的大量问题,本质都在问:
这个元素现在是不是还在普通文档流里?
例如:
- 为什么父元素高度塌了?
- 为什么元素重叠了?
- 为什么后面的元素顶上来了?
- 为什么
absolute元素不占位置? - 为什么
float后需要清除浮动? - 为什么
flex/grid后子元素排法变了?
这些都和“是否按普通文档流排”直接相关。
八、几个最容易混淆的点
1. relative 不会脱离文档流
.box {
position: relative;
top: 10px;
}
它只是视觉上偏移了,但原来占的位置还在。
所以:
relative:不脱离普通文档流absolute/fixed:脱离普通文档流
2. display: none 不是“脱离文档流”,而是直接没了
`display: none`` 的效果不是“它还在,但脱流了”,而是:
元素直接不参与渲染和布局了。
它比“脱流”更彻底。
3. flex / grid 不是简单“脱离文档流”
父元素设置 display: flex 或 display: grid 后,子元素不是跑没了,而是:
子元素不再按普通流的块/行内规则排列,而是按 flex / grid 规则排列。
这和 absolute 那种脱流不是一回事。
九、一张表总结
| 概念 | 是否还按普通文档流排 | 说明 |
|---|---|---|
| 普通块级元素 | 是 | 从上到下,一个接一个 |
| 普通行内元素 | 是 | 在一行中从左到右 |
position: relative | 是 | 还占原位置,只是视觉偏移 |
position: absolute | 否 | 脱离普通文档流 |
position: fixed | 否 | 脱离普通文档流 |
float | 部分脱离常规影响 | 会改变普通流表现 |
display: flex 子项 | 不按普通块/行内排 | 按 flex 规则排 |
display: grid 子项 | 不按普通块/行内排 | 按 grid 规则排 |
十、结论
普通文档流本质上就是:
浏览器在没有特殊干预时,对页面元素进行默认排版的基础秩序。
你只要抓住这句话,很多 CSS 现象都会立刻变清晰:
- 正常元素为什么会按顺序排
- 为什么块级元素是竖着堆
- 为什么行内元素是横着流
- 为什么
absolute会不占位置 - 为什么布局一复杂就总绕回“文档流”
最后再压缩成一句最适合记忆的话:
学布局,先判断元素是不是还在普通文档流里。
这一步判断对了,后面大半问题都会变简单。