<meta charset="UTF-8">必须是<head>第一个子元素,因浏览器提前扫描前1024字节确定编码,若其前存在注释、<title>或模板语法,将导致中文乱码、JS报Invalid or unexpected token错误。

必须把 <meta charset="UTF-8"> 放在 <head> 的第一个子元素位置,且所有属性值一律用双引号包裹——这两点不是“建议”,是工程化落地的硬门槛。
为什么 <meta charset="UTF-8"> 必须是 <head> 的第一个子元素
浏览器解析 HTML 时,会提前读取前 1024 字节来确定编码。如果 <meta charset="UTF-8"> 不在最前面,中间夹了注释、<title> 或模板语法(如 <% if %>),就可能被跳过,导致中文乱码、JS 报 Invalid or unexpected token 错误。
- 正确顺序:
<head><meta charset="UTF-8"><title>... - 错误写法:
<head><!-- 注释 --><title>...<meta charset="UTF-8">(注释或<title>在前) - 服务端模板(EJS/Django)中,确保
<meta charset="UTF-8">不被任何逻辑块包裹或延迟渲染 - HTTP 响应头中的
Content-Type: text/html; charset=UTF-8是兜底手段,但不能替代 HTML 内部声明——两者都要,且 HTML 内部声明优先级更高
class、src、alt 等所有属性值必须用双引号,不是为了“好看”
单引号或不加引号在某些构建工具(如旧版 Webpack 插件)、CI 检查(HTMLHint)或 SSR 渲染中会直接报错,而且空格、括号等字符会让解析器截断属性值。
- 合法:
<img src="logo.png" alt="公司标识" data-id="123"> - 非法:
<img src=logo.png alt='logo'>(单引号 + 无双引号)、<img src=logo.png>(无引号)、<img alt="">(空字符串必须写成alt="",不能省略) - 布尔属性如
disabled、required要写成disabled或disabled="",不要写disabled="disabled" - Prettier 默认会修正引号,但团队成员手动删掉后提交,就会触发 Git Hooks 中的 HTMLHint 检查失败
属性顺序不是风格问题,是 diff 可读性的分水岭
当多人修改同一段 HTML,class 和 id 位置来回变动,Git diff 就全是“行移动”,真实修改被淹没。
立即学习“前端免费学习笔记(深入)”;
- 推荐顺序:
class→id→name→data-*→src/href/for/type→title/alt→aria-*/role→style(靠后,因易变) - HTMLHint 规则
attr-order可启用,但需配合 Prettier 的htmlWhitespaceSensitivity和自定义prettier.config.js才能稳定生效 -
lang属性必须出现在<html>标签上,且值为zh-CN(不是zh、cn或zh-cn),否则屏幕阅读器和 SEO 工具识别失败
工程化落地:光配规则没用,得卡在保存和提交两个环节
靠人眼 review 几乎拦不住漏引号、错顺序、少 lang 这类低级错误。真正起作用的是机器自动拦截。
- VS Code 安装
HTMLHint插件 + 启用htmlhint.autoFixOnSave,保存即修正基础问题 - Git Hooks 配置
pre-commit调用htmlhint "**/*.html",提交前全量检查 -
.htmlhintrc至少启用:doctype-first、meta-charset-require、html-lang-require、attr-lowercase、attr-quote-style、attr-order - CI 流程中增加
npm run lint:html步骤,失败即阻断发布
最容易被忽略的其实是模板引擎里的顺序陷阱——<meta charset="UTF-8"> 看似写对了,却被 <% if %> 包裹或插在 <title> 后面;还有人把 lang 写成 zh,以为“简体中文”就够了,结果语音合成直接哑火。



















