必须放在里,因HTML解析器在构建DOM前就提取其内容用于标签页、收藏夹和SEO;写在中会被部分浏览器忽略或错位,导致标题不显示。

浏览器标签页显示的标题,只认 里的第一个 标签;写错位置、重复写、用 JS 改 DOM 节点,全都不生效。
为什么 必须放在 里
HTML 解析器在构建 DOM 前就提取 内容用于标签页、收藏夹和搜索引擎摘要。它不是“渲染后才起作用”的元素,而是解析阶段就锁定的元信息。写在 里时,Chrome 可能自动挪进 ,但爬虫、旧版 Safari WebView、微信内置浏览器直接忽略——你看到标签页显示 index.html 或“无标题”,就是这个原因。
常见错误包括:
-
被模板引擎(如 EJS 的首页 )插到了开头 - 手写 HTML 漏了
标签,直接跟在后面 - Vue/React 项目开了 SSR,但服务端没注入真实标题,首屏 HTML 里
是空的或默认值
动态改标题只能用 document.title,别碰 DOM
单页应用路由切换时,很多人写 document.querySelector('title').textContent = '新标题',这行代码确实能改 DOM 节点,但浏览器标签页文字完全不变——因为规范明确要求:只有赋值 document.title 才触发标题更新逻辑。
注意几个硬限制:
- IE6–8 对中文支持差,必须确保页面有
且与文件实际编码一致 - 修改后不触发任何事件,无法用
addEventListener监听变化 - 微信/QQ 分享卡片取的是初始 HTML 中的
,JS 后改的只影响当前标签页 - 不要在
setTimeout里延迟设置,应绑定到框架的路由就绪钩子(如 Vue Router 的afterEach、React Router 的useEffect+location.key)
构建工具会悄悄覆盖你写的
Vite 的 vite-plugin-html、Webpack 的 html-webpack-plugin 默认通过配置项注入标题,比如 title: '我的网站'。这时你源码里写的 看着正常,构建后生成的 index.html 里早就被替换成插件生成的内容。
排查方法很简单:
- 别看源码,直接打开 dist 目录下的
index.html,搜索 - 检查插件配置是否启用了
templateParameters或inject: true - 需要自定义时,优先用插件提供的变量注入(如
),而不是硬写静态文本
内容的长度和字符陷阱
搜索引擎通常只展示前 50–60 字符,移动端标签栏更窄——12 个汉字就可能被截断。更危险的是未转义字符:
-
&必须写成&,否则会被当成实体开头,导致标题截断甚至 HTML 解析失败 和>必须写成和>,否则破坏 HTML 结构- 中文、emoji、©、— 可以直接写,但全角空格、BOM 字符、零宽空格会导致解析异常
- 禁止出现
<script></script>、{{ title }}、onclick=等任何非纯文本内容
最常被忽略的一点: 不只是展示字段,它参与页面唯一性判定、history.state 关联、PWA 安装横幅文案生成——一旦初始为空或错误,后续补救成本远高于一开始就写对。











