必须顶格写在第一行且不能带空格,因为它是浏览器切换标准模式与怪异模式(quirks mode)的唯一指令;若前面有空格、bom、注释或大小写混用,将触发怪异模式,导致box-sizing失效、getboundingclientrect()偏移、表单submit异常等问题。

为什么 必须是第一行且不能带空格
浏览器靠它切换渲染模式:写错或前面有空格/BOM,就会进 Quirks Mode,导致 box-sizing 失效、getBoundingClientRect() 偏移、表单 submit 行为异常。实测在 Edge 旧版和部分安卓 WebView 中尤其明显。
常见错误包括:(大小写混用)、<code><!-- 注释 -->(前面有注释)、<code>(末尾多空格)。只要不是严格的小写 <code> 且独占首行,就可能出问题。
建议做法:
- 用 VS Code 或 HBuilder 新建文件后直接敲
!+ Tab,自动生成标准结构,避免手误 - 保存前检查文件开头是否有不可见字符(可用十六进制编辑器或命令行
head -c 10 index.html | hexdump -C验证) - 服务端返回 HTML 前,确保模板引擎没在 doctype 前注入空格或换行
不只是 SEO 配置
这个属性直接影响屏幕阅读器语调、拼写检查词典、CSS 的 :lang(zh-CN) 选择器匹配,甚至影响某些字体 fallback 行为。写成 lang="zh" 或留空,在 iOS VoiceOver 和 Windows Narrator 中常导致发音生硬或跳过整段。
真实场景中容易被忽略的点:
- 多语言页面里,局部内容要用
<section lang="en"></section>覆盖,而不是只靠根元素 - 服务端渲染时,必须从请求头
Accept-Language动态生成,硬编码zh-CN会坑到海外用户 - 使用 i18n 框架(如 i18next)时,别忘了同步更新
的lang属性,否则 CSS:lang()规则不生效
<meta charset="UTF-8"> 必须紧贴 后
它得在 最前面——不是“随便放 head 里就行”。如果前面有其他 <meta> 或 <title></title>,浏览器可能已用默认编码(如 ISO-8859-1)解码了前几个字节,造成开头中文乱码且无法挽回。
使用 Puppeteer + Chrome 将 HTML 渲染为中文 PDF,自动处理图表等待、Tab 展开、动画、测高、白边消除、防分页,适用于看板、报表、网页和交互图表转 PDF。
典型翻车现场:
- 复制别人代码时把
<title></title>写在<meta charset>前面 - 模板引擎里
{% block head %}插入顺序没控制好,导致charset被挤到后面 - Webpack HtmlWebpackPlugin 默认把
charset放中间,需显式配置meta: { charset: 'utf-8' }并确认插入位置
里直接塞 <div> 不报错,但代价不小<p>浏览器能渲染,不代表合理。语义缺失会让无障碍工具无法建立层级,搜索引擎降低可信度,连 <code>display: contents 这种现代 CSS 特性在无结构区域都表现异常。
起步阶段至少该做三件事:
- 用
<header></header>、<main></main>、<footer></footer>替代纯<div> 包裹<li>标题必须用 <code><h1></h1>–<h6></h6>,别全用<p style="font-size:24px"></p> - 段落内容包在
<p></p>里,哪怕只有一行文字——这是最基础的语义锚点
真正麻烦的不是写错标签,而是后期加无障碍支持或 SEO 优化时,发现整个 是平铺的 div 海洋,重构成本远超预期。










