html结构必须严格遵循语义化规范:doctype须顶格首行、lang需用bcp 47标准如zh-cn、charset必须在head前1024字节内、标签嵌套须守层级铁律,否则影响解析、无障碍、seo及js执行。

HTML 标签不是随便套个 <div> 就能撑起结构的,错用、漏用或嵌套失序会直接让 DOM 解析失败、无障碍工具读不出层级、SEO 抓不到主干,甚至导致 JS 获取不到 <code>document.body。
为什么 必须顶格写在第一行
浏览器一读到非空白字符就决定解析模式。前面哪怕一个 BOM 字节、空行或注释,IE 和部分旧内核立刻进怪异模式(document.compatMode === "BackCompat"),后果包括:box-sizing 失效、flex 排列错乱、position: sticky 不工作,连 document.title 都可能读成空字符串。
或 <code> 写法虽不报错,但某些 CI 流程会因格式校验失败阻断部署- VS Code 输入
!+ Tab 生成的模板最稳妥,别手动删空格或加换行 - 它不是标签,是触发标准模式的唯一指令——没它,后面所有语义化努力都打折扣
不能简写成 lang="zh"
只写 lang="zh" 看似省事,实际会让屏幕阅读器默认用台湾腔或日语发音逻辑,拼写检查器匹配不到简体词库,Google 搜索也倾向返回繁体结果。BCP 47 标准要求地区码明确。
- 服务端渲染(SSR)场景下,若语言动态切换,
lang值必须和服务端输出一致,否则 React/Vue hydration 会因 DOM 差异报错 - 嵌套英文内容时,用
<p lang="en">API response</p>覆盖即可,不用额外设xml:lang - 别写
lang=""——这等价于未声明,浏览器按undefined处理
<meta charset="UTF-8"> 必须在 开头 1024 字节内
浏览器只扫描 前 1024 字节来确定字符集。如果它被夹在 <title></title> 后面、或中间有 JS 注释,中文就会显示为 ,且该乱码不可逆(刷新也不恢复)。
- 推荐顺序:
</meta charset="UTF-8">→<meta name="viewport">→<title></title> - 不要用已废弃的
<meta http-equiv="Content-Type">,Chrome 120+ 会忽略 - 大小写敏感:
UTF-8正确,utf8或UTF8都不行
语义化标签嵌套不能靠直觉,要守层级铁律
<main></main> 每页只能出现一次,且必须是 的直接子元素;<nav></nav> 只用于导航区块,不能塞进 <footer></footer> 里当“友情链接”;<section></section> 必须自带标题(<h2></h2>~<h6></h6>),否则对读屏软件就是无意义容器。
-
<ul></ul>/<ol></ol>必须直接包<li>,里面塞<div> 会导致 NVDA、VoiceOver 无法识别列表项数量 <li> <code><h1></h1>应代表页面主主题(如 logo 或核心标题),之后用<h2></h2>→<h3></h3>逐级展开,跳级(比如<h2></h2>后直接<h4></h4>)会让读屏软件逻辑断裂 -
<header></header>不等于“顶部栏”,它应包含当前作用域的引导性内容(如文章页的<h1></h1>+ 作者 + 发布时间),而非全站通用 header
真正难的不是记住这些规则,而是每次写新页面时,都得重新判断:这个 <div> 真的不能换成 <code><aside></aside>?那个 <section></section> 有没有配标题?浏览器和读屏软件不会给你二次机会——DOM 一旦生成,结构错误就固化了。











