<p>标题 <div class="blk">一块内容</div> 说明文字</p>
实际渲染成三段,中间的 div 把 <p> 提前关掉了:
标题
<p> 的内容模型禁止任何块级元素。浏览器遇到 <div> 会自动闭合前面的 <p>,不会报错,结构却与你想的完全不同。
<p>标题</p> <div class="blk">一块内容</div> <p>说明文字</p>
<ul> <li>第一项 <li>第二项 </ul> <b><i>交叉</b></i> <table><tr><td>缺 tbody</table>
浏览器全都「接受」了:省略 </li> 合法、<table> 会自动补 tbody,但交叉嵌套会被拆成 <b><i></i></b><i></i>,斜体跑到外面去了。
DevTools Elements 面板里看缩进层级,与源码对不上的地方就是被纠正过的。或直接在 Console 里问:
document.querySelectorAll('i').length
// 期望 1,实际 2 —— 浏览器替你补了一个
另一条通用手段:把文件过一遍校验器(W3C Nu Validator、或编辑器里的 HTML 校验插件),它会明确告诉你「element i not allowed as child of …」。
| 现象 | 真实原因 | 修法 |
|---|---|---|
| 表格列整体错位 | 合并单元格后没删被盖住的 <td> | 数一下每行的列数: colspan/rowspan 计入被合并的那些 |
| 读屏只念数字不念表头 | <th> 缺 scope | 列表头 scope="col",行表头 scope="row" |
| 后端收不到某个字段 | 控件只有 id 没有 name | 补 name;id 与提交无关 |
| 点标题文字不聚焦输入框 | <label for> 与 id 不一致,或 id 重复 | 成对检查;同名 id 只命中第一个 |
| 提交按钮一点就刷新整页 | 表单里 <button> 默认 type="submit" | 非提交按钮显式写 type="button",JS 里 e.preventDefault() |
| 单选组选了两个 | 同组 radio 的 name 不同 | 一组同名,value 区分选项 |
src 写成了相对 ../../。html{height:100%} 或改用 min-height/aspect-ratio。怪异模式下这条更常见(document.compatMode 检查)。position:relative(static 不建立定位参照)。这类问题的 HTML 通常没错,是 CSS 的问题。| 步骤 | 做什么 | 能解决什么 |
|---|---|---|
| 1 | 刷新前先关掉浏览器扩展(尤其广告拦截、隐私插件) | 「本地正常、别人打不开」的第一大来源 |
| 2 | DevTools Console 有没有红色报错;Network 面板有没有红色 4xx/5xx | 资源路径、接口、CORS 问题 |
| 3 | Elements 面板看实际 DOM 与 Computed 样式,而不是看源码 | 浏览器自动纠正、样式覆盖、继承结果 |
| 4 | 用排除法:把出问题的片段复制到独立 HTML 里,只留最小结构 | 定位是哪个嵌套/哪个样式引起的 |
| 5 | 过一遍 Nu 校验器 + Lighthouse | 结构非法、对比度、缺 label、缺 title |
| 6 | 窄屏 375px 与键盘 Tab 各走一遍 | 响应式与可访问性问题只在真机上暴露 |
最后一句:HTML 的错误绝大多数不会报错——它的设计目标就是「尽力理解你写的东西」。所以排查靠的是「对比实际 DOM 与预期 DOM」,而不是等控制台提示。