新手写网页最常翻车的是HTML格式化细节:DOCTYPE前不能有BOM或空格,meta charset必须为UTF-8且在title前,lang值须符合IANA标准(如zh-CN),body必须正确嵌套且为html唯一直系子元素。

新手写网页最常翻车的不是逻辑,而是 HTML 格式化细节——这些地方不报错,但会让浏览器猜、让 JS 失效、让 QA 在安卓机上一眼崩溃。
DOCTYPE 前不能有任何字符,包括空格和 BOM
现象:页面在 Safari 或旧版 Android WebView 里 flex 布局错乱、100vh 高度失效、getBoundingClientRect() 返回 { top: 0, left: 0 } 异常值。
原因:<!DOCTYPE html> 必须是文件第一字节,前面哪怕一个 UTF-8 BOM(EF BB BF)或空格,浏览器就直接退化进怪异模式(Quirks Mode)。
实操建议:
- 用 VS Code 打开文件,右下角确认编码显示为
UTF-8,不是UTF-8 with BOM - Sublime Text 保存时选
Encoding → UTF-8,别选带 BOM 的版本 - CI 流水线可加校验脚本:
head -c 10 file.html | hexdump -C查看开头是否为3c 21 44 4f 43 54 59 50 45(即<!DOCTYPE的 ASCII 十六进制)
meta charset 必须写成 UTF-8,且必须在 之前
现象:中文变方块、Ajax 返回的 JSON 中文字段乱码、邮件客户端渲染失败。
原因:</meta charset="utf-8"> 或 <meta charset=utf8> 都是错的——W3C 只认 UTF-8(大写 U、T、F,短横线,大写 E),且该标签必须出现在 <head> 最靠前位置,**必须在 <title> 之前**;否则浏览器已按默认编码(如 ISO-8859-1)开始解析标题内容,再读到 charset 就晚了。
实操建议:
- 固定写法:
<meta charset="UTF-8">,大小写和连字符一个都不能错 - 检查构建工具(Vite/Webpack)的 HTML 插件配置,确保没把
<title>注入到<meta charset>前面 - 服务端渲染(Next.js/Nuxt)需确认模板拼接顺序,
<html>开始后第一行必须是<meta charset="UTF-8">
lang 属性值必须来自 IANA,不能写 zh 或 cn
现象:屏幕阅读器跳过主内容、Google 搜索结果中显示“语言未指定”、拼音输入法在表单中异常。
原因:<html lang="zh"> 或 <html lang="cn"> 不符合 BCP 47 标准,会被视为无效值,等同于未声明。多语言站点若静态写死 lang="zh-CN",但实际返回英文内容,反而误导辅助技术。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 中文简体站用
zh-CN或zh-Hans,繁体站用zh-TW或zh-Hant - 动态多语言项目,服务端应根据用户请求头
Accept-Language输出对应lang,前端 JS 不要覆盖 document.documentElement.lang - CI 可加正则校验:
grep -q 'lang="\(zh-CN\|zh-Hans\|en-US\|en-GB\)"' index.html
body 里不能漏写,也不能写错嵌套顺序
现象:document.body 为 null、CSS 选择器 body > p 不生效、SEO 工具提示“无主体内容”。
原因:<body> 是唯一合法承载可视内容的容器,所有可渲染内容必须在它内部;<head> 和 <body> 是 <html> 的唯一直系子元素,顺序不能颠倒,也不能嵌套在其他标签里。
实操建议:
- 手写时牢记结构:
<html><head>...</head><body>...</body></html> - CMS 或 SSR 模板中,避免拼接出类似
<body><head>...的错误顺序 - 用 DevTools 的 Elements 面板快速验证:展开
<html>后,只应看到两个子节点:<head>和<body>
真正麻烦的不是写错,而是“看起来能跑”——这些格式化细节不抛 JS 错误,却会在特定设备、特定辅助工具、特定网络环境下突然失效,而且很难复现。检查时优先盯住文件开头那十行。



















