type="email"仅校验基础格式:含@、前后有字符、@后带点及至少两字母顶级域;不查域名存在性、不发请求、不验MX、不trim空格。

type="email" 会自动校验什么
它只校验基础格式:必须含一个 @,@ 前后都得有字符,且 @ 后必须带点(.)和至少两个字母的顶级域(如 .com、.org)。不查域名是否存在,不发请求,不验证 MX 记录,也不 trim 空格。
典型合法值:user@example.com、test+tag@sub.co.uk
典型非法值:user@、@example.com、user@example、 user@example.com (首尾空格不自动清理)
- 浏览器仅在调用
form.checkValidity()、input.reportValidity()或表单提交时触发校验 - 移动端 Safari 可能将
type="email"渲染为普通文本框,但校验逻辑仍生效 - Chrome / Edge 会自动弹出邮箱专用软键盘;iOS Safari 也支持,但部分旧版本 fallback 为数字键盘
required + placeholder 怎么配才不翻车
required 是必填开关,但它只在提交或显式调用校验方法时起作用;placeholder 只是视觉提示,不能替代 label,也不能被屏幕阅读器可靠读取。
- 必须写
<label for="email">邮箱地址</label>,不能只靠placeholder="name@example.com" -
placeholder写具体样例比写“请输入邮箱”更有效,尤其对移动端用户 - Safari 对
::placeholder的渲染高度兼容性差,某些版本会截断文字,建议加line-height和padding微调 - 如果用了
novalidate在<form>上,required会完全失效,需 JS 手动补全
setCustomValidity() 的坑在哪
这是控制错误文案的核心 API,但极易误用:只要传入非空字符串,原生校验就彻底让位给你;而一旦设过错误消息,不手动清空,状态就锁死——哪怕用户已输对,仍报错。
- 每次输入后都得调
input.setCustomValidity(''),否则后续校验永远失败 - 适合搭配
blur事件做轻量业务校验(比如检查常见域名gmail.com、qq.com),而非input频繁触发 - 错误文案不支持 HTML,纯文本;浏览器默认提示无法翻译,只能覆盖
- 若同时用了
pattern属性,setCustomValidity()会优先级更高,原生 pattern 提示不会出现
后端为什么必须重新校验
前端 type="email" 校验只是体验层优化,不是安全边界。用户可以禁用 JS、绕过 HTML 属性、用 curl 直接 POST 任意字符串。
立即学习“前端免费学习笔记(深入)”;
- 后端必须独立执行 RFC 兼容的邮箱解析(如用
email-validator库或等效正则),不能信任req.body.email已清洗 - 务必
trim()再校验,前端空格不会自动去除 - 若需强一致性(如注册唯一性),域名有效性、MX 记录探测、甚至发送验证邮件,都得由后端发起
- 多个邮箱用
multiple时,后端收到的是逗号分隔字符串("a@b.com,c@d.org"),需手动 split + 逐个校验
setCustomValidity('') 的清空时机和后端对空格的处理——这两处出问题,线上就会出现“用户明明输对了却提交不了”或“数据库存进带空格的邮箱”这类低级但难复现的故障。



















