文档流起点由tokenizer扫描到标签时锚定,树构建器以此为根按源码顺序挂载子节点,该挂载顺序即文档流原始坐标系;所有成功进入dom树的节点(除display: none外)均严格参与此初始流。

Tokenizer遇到就锚定文档流起点
文档流不是靠CSS触发的,也不是从第一行HTML文本开始“流动”的——它由HTML解析器在词法分析(tokenization)阶段就已确定。一旦Tokenizer扫描到标签,树构建器立刻以该节点为根,按源码顺序挂载后续子节点;这个挂载顺序就是文档流的原始坐标系。
常见错误是以为“没写CSS,元素就自由排列”,其实只要没被display: none干掉,所有成功进入DOM树的节点(包括<my-card></my-card>这类未定义自定义元素)都严格参与这个初始流。而<script></script>里未执行的JS、<template></template>内容、或document.write()动态插入但尚未被解析的片段,压根不会出现在这个流里。
-
<meta charset="utf-8">若缺失或位置超出前1024字节,Tokenizer解码错乱,后续文本令牌崩坏,DOM节点内容异常——流还在,但语义已不可信 -
<noscript></noscript>里的内容只在JS禁用时才参与流,启用状态下直接跳过 - 嵌套超过6层(比如
<div><div><div><table><tr><td><div>)可能被流式解析器主动截断丢弃,尤其在低端设备上 <h3>DOM树构建顺序 = 文档流原始坐标系</h3> <p>浏览器边下载HTML边解析,不等完整文件就启动Tokenizer。DOM树是逐行构建的:遇到<code><h1></h1>就建节点,遇到<p></p>就作为子节点挂到当前父容器下,遇到未闭合的<p></p>或错位嵌套(如<div><p></p></div>),解析器会按容错规则自动修复,不报错但DOM结构与你写的源码不一致。这意味着:你在代码里写的顺序,就是元素在文档流中默认占据空间的先后顺序。块级元素(
<div>、<code><p></p>、<section></section>)自上而下堆叠,行内元素(<span></span>、<strong></strong>、<a></a>)自左至右填满当前行再换行——这不是CSS“安排”的,是解析器挂载节点时就定死的几何关系。-
<script></script>没加defer或async,放在中间?解析器立刻暂停DOM构建,等JS下载执行完才继续——首屏内容卡在半路,根本进不了流 -
<link rel="preload">或<script defer></script>不影响Tokenizer,但会改变资源加载优先级 - 用DevTools右键任意节点 →
Show DOM properties查depth值,超6就该拆结构,别硬扛
display: none 是唯一彻底退出文档流的方式
其他看似“隐藏”的方式,其实都在流里占着坑:
visibility: hidden和opacity: 0只是让像素不可见,布局计算照常进行;float: left让元素脱离流但文本绕排,父容器高度坍缩;position: absolute完全脱离流,定位参考点取决于最近非static祖先——没设的话就回退到,嵌套深了极易偏移。display: flex和display: grid会创建新格式化上下文(BFC),子项按新规则布局,但容器自身仍参与外层文档流;而display: none是唯一让渲染树直接跳过该节点的方式——不占空间、不触发重排、DOM节点存在但不出现在渲染树里。- 用
<div>替代<code><button></button>又没设display: inline-block?默认display: block独占一行,在导航栏里强行换行 <td>内嵌套过深会放大样式重排风险,语义标签如<code><section></section>、<main></main>不增加解析成本,还能压低实际DOM节点数- 移动端建议DOM节点总数≤800,否则解析和重排压力陡增
DOCTYPE缺失时文档流还在,但行为不可控
删掉
页面照样显示,是因为浏览器启用怪异模式(Quirks Mode),模拟IE5行为——文档流依然存在,但盒模型、百分比计算、垂直对齐等规则全变了。这时候你写的<code>width: 100%可能算错,margin: auto居中可能失效,连<table>的边框渲染都可能错位。 <p>更隐蔽的问题是:怪异模式下,解析器对嵌套错误、自闭合标签的容错逻辑也不同,DOM树结构更容易偏离预期。哪怕你肉眼看着正常,自动化测试或屏幕阅读器可能已经读歪了。</p> <ul> <li>必须把<code><meta charset="UTF-8">放在前1024字节内,否则编码错乱导致后续所有文本解析失败 -
-
里<script></script>会阻塞后续HTML解析,但<link>不会——CSS下载和HTML解析并行,只是渲染要等CSSOM完成 - 流式解析没有“回溯”机制,写错的结构(比如漏写
)只会被修复一次,修复结果未必是你想要的
被Tokenizer识别时就锁死了。之后所有CSS和JS的干预,都是在这个初始坐标系上做覆盖、退出或重排——而不是重新定义“流”本身。真正容易被忽略的是:解析器不校验你的意图,只忠实执行容错规则;你看到的DOM结构,未必是你写的源码结构。











