<meta charset="UTF-8"> 必须是 <head> 的第一个子元素,浏览器仅在前1024字节内查找该标签,若位置靠后或被注释、BOM、script等干扰,将回退至系统默认编码(如GBK或ISO-8859-1),导致中文及emoji乱码;正确写法是紧随 <head> 开始即写,且全文唯一。

meta charset 必须是 的第一个子元素
浏览器在解析 HTML 时,会在前 1024 字节内查找字符编码声明。如果 <meta charset="UTF-8"> 不在 最开头,部分浏览器(尤其是旧版 IE)可能直接忽略它,回退到系统默认编码(如 Windows-1252 或 ISO-8859-1),导致中文、日文、阿拉伯文等多字节字符显示为乱码()。
常见错误写法包括:
- 在
<meta charset>前插入了<script></script>或<style></style> - 把
<meta charset>放进里 - 用过时的
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
正确写法只有一种:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>页面标题</title> <!-- 其他 meta、link、script 紧随其后 -->
form accept-charset 是 POST 提交的强制保险
即使页面已声明 UTF-8,<form></form> 默认仍可能按浏览器 locale 编码提交数据(例如某些 Safari 版本对非 ASCII 字符用 ISO-8859-1)。服务端收到的原始字节流一旦错乱,后续任何解码补救都无效。
立即学习“前端免费学习笔记(深入)”;
必须显式设置:
- 所有
<form method="post"></form>都加accept-charset="UTF-8" - 不要依赖
<meta charset>自动继承 —— 它不作用于表单提交 - 若使用 AJAX(如
fetch),需手动设置 header:headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }
示例:
<form method="post" accept-charset="UTF-8"> <input name="name" placeholder="请输入姓名"> <button type="submit">提交</button> </form>
lang 属性必须匹配 IANA 注册值
lang 不是随便写的字符串,它直接影响屏幕阅读器发音、搜索引擎语言识别、字体回退逻辑,甚至影响某些 CSS 伪类(如 :lang(zh))的行为。错误值(如 lang="cn" 或 lang="ch")会导致这些功能失效或误判。
正确做法:
- 中国大陆用
lang="zh-CN",台湾地区用lang="zh-TW",香港用lang="zh-HK" - 多语言页面中,局部内容需单独标注,如:
<span lang="ja">こんにちは</span> - 避免仅写
lang="zh"—— 它表示“泛中文”,但缺乏区域信息,字体渲染和排版可能不如具体子标签精准
服务端与前端 UTF-8 必须全链路对齐
前端写对了 meta 和 accept-charset,不代表后端就安全了。常见断点:
- PHP:没调
mb_internal_encoding('UTF-8'),或default_charset未设为"UTF-8" - Node.js(Express):没配
express.urlencoded({ extended: true, type: 'application/x-www-form-urlencoded' }),或漏掉encoding参数 - Java Servlet:没在
request.getParameter()前调request.setCharacterEncoding("UTF-8") - 数据库:MySQL 表/列用的是
utf8而非utf8mb4,存 emoji 或生僻汉字会截断
最易被忽略的一点:HTTP 响应头中的 Content-Type 如果没带 charset=UTF-8(如只返回 text/html),部分浏览器会无视 meta 标签,直接按响应头判断编码 —— 这个优先级高于 HTML 内容。



















