email 邮箱输入
type="email" 是 HTML5 专为邮箱地址设计的输入控件。浏览器不仅会为移动设备提供优化的虚拟键盘(包含 @ 和 .com 快捷键),还会在表单提交时自动验证输入值是否符合邮箱格式。本节将详细讲解邮箱输入的验证机制、multiple 属性的多邮箱模式,以及使用 pattern 进行补充验证。
前置知识
阅读本节前,建议先了解:password 密码输入
基础概念
什么是 email 输入
type="email" 创建一个专门用于输入电子邮件地址的输入框。它在功能上与 type="text" 相似,但增加了:
- 自动格式验证:提交时浏览器检查是否为合法邮箱格式
- 移动端键盘优化:在手机上弹出包含
@和.的邮箱键盘 - 语义化:辅助技术可以正确识别这是一个邮箱输入框
<!-- 基本 email 输入 -->
<input type="email" name="email" placeholder="user@example.com">
<!-- 自动验证:提交时检查格式 -->
<form>
<input type="email" name="email" required>
<!-- 输入 "hello" 提交时,浏览器会阻止并提示 -->
<!-- 输入 "hello@example.com" 提交时,验证通过 -->
<button type="submit">提交</button>
</form>email 的核心特征
| 特征 | 说明 |
|---|---|
| 输入方式 | 键盘输入 |
| 数据类型 | 邮箱地址字符串 |
| 自动验证 | 是(检查是否包含 @ 和域名) |
| 移动端键盘 | 邮箱键盘(含 @ 和 .com) |
| 支持属性 | 与 text 相同 + multiple |
语法
基本语法
<input
type="email"
name="email"
id="email"
placeholder="user@example.com"
required
multiple
autocomplete="email"
pattern="自定义正则"
list="datalistId"
>专有/常用属性
| 属性 | 值 | 说明 |
|---|---|---|
type | "email" | 指定为邮箱输入 |
multiple | 布尔属性 | 允许输入多个邮箱(逗号分隔) |
autocomplete | "email" | 自动补全为邮箱地址 |
pattern | 正则表达式 | 自定义验证规则(补充浏览器默认验证) |
详细说明
浏览器自动验证规则
浏览器对 type="email" 的默认验证规则比较宽松,只检查值是否符合 value@domain 的基本格式:
验证通过的示例:
user@example.comtest@sub.domain.orga@b.c(最短的有效格式)
验证失败的示例:
user(缺少@和域名)user@(缺少域名)@example.com(缺少用户名)user@@example.com(多个@)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>email 自动验证</title>
<style>
label { display: block; margin-bottom: 4px; font-weight: 500; }
input { padding: 8px; border: 1px solid #ccc; border-radius: 4px; width: 300px; }
.demo { margin-bottom: 20px; padding: 12px; border: 1px solid #e0e0e0; border-radius: 8px; }
</style>
</head>
<body>
<h2>email 自动验证演示</h2>
<div class="demo">
<p>浏览器默认验证比较宽松,只检查基本格式:</p>
<form>
<label for="email1">输入邮箱后点击提交:</label>
<input type="email" id="email1" name="email" required>
<button type="submit">验证</button>
</form>
<p style="color: #999; font-size: 13px; margin-top: 8px;">
试试输入 "hello"(失败)和 "hello@world.com"(成功)
</p>
</div>
<!--
以下值都会通过浏览器的默认验证(可能不符合实际邮箱规则):
- a@b.c (极短的域名)
- user@localhost (没有点号)
- user@192.168.1.1 (IP 地址域名)
-->
</body>
</html>关于验证宽松性
浏览器的默认邮箱验证故意设计得比较宽松,因为邮箱格式的完整规范(RFC 5322)非常复杂,严格验证会拒绝很多合法的邮箱地址。如果需要更严格的验证,应使用 pattern 属性或 JavaScript。
multiple 多邮箱模式
multiple 属性允许用户在一个输入框中输入多个邮箱地址,用逗号分隔。提交时,整个字符串作为一个字段值发送。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>multiple 多邮箱</title>
<style>
.form-group { margin-bottom: 16px; }
label { display: block; font-weight: 500; margin-bottom: 6px; }
input { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; }
.hint { font-size: 13px; color: #999; margin-top: 4px; }
</style>
</head>
<body>
<h2>发送邮件邀请</h2>
<form action="/api/invite" method="post">
<div class="form-group">
<label for="to">收件人(多个邮箱用逗号分隔)</label>
<input type="email"
id="to"
name="to"
multiple
required
placeholder="a@example.com, b@example.com, c@example.com">
<p class="hint">多个邮箱地址之间用逗号分隔</p>
</div>
<div class="form-group">
<label for="subject">主题</label>
<input type="text" id="subject" name="subject" placeholder="邀请标题">
</div>
<button type="submit">发送邀请</button>
</form>
<!--
提交时 to 字段的值:
to=a%40example.com%2C+b%40example.com%2C+c%40example.com
服务器解码后:
to = "a@example.com, b@example.com, c@example.com"
服务器需要用逗号分割来获取各个邮箱地址
-->
</body>
</html>multiple 的验证行为
当使用 multiple 时,浏览器会验证每个逗号分隔的值都是合法邮箱。例如 "a@b.com, invalid, c@d.com" 会导致验证失败,因为中间的 invalid 不是合法邮箱。
pattern 正则补充验证
如果浏览器的默认验证不够严格,可以使用 pattern 属性添加自定义正则规则。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>pattern 补充验证</title>
<style>
.form-group { margin-bottom: 20px; }
label { display: block; font-weight: 500; margin-bottom: 6px; }
input {
width: 100%;
max-width: 400px;
padding: 10px 12px;
border: 1px solid #ccc;
border-radius: 6px;
box-sizing: border-box;
}
/* 实时验证样式 */
input:valid:not(:placeholder-shown) {
border-color: #27ae60;
}
input:invalid:not(:placeholder-shown):not(:focus) {
border-color: #e74c3c;
}
.hint { font-size: 13px; color: #999; margin-top: 4px; }
</style>
</head>
<body>
<h2>邮箱注册</h2>
<form action="/register" method="post">
<!-- 基本邮箱验证(浏览器默认) -->
<div class="form-group">
<label for="email1">基本验证(浏览器默认)</label>
<input type="email" id="email1" name="email" required
placeholder="如 user@example.com">
<p class="hint">浏览器自动验证,只检查基本格式</p>
</div>
<!--
严格验证:限制为常见邮箱格式
- 用户名部分:字母、数字、点、下划线、连字符
- 域名部分:至少一个点号分隔
- 顶级域名:至少2个字母
-->
<div class="form-group">
<label for="email2">严格验证(pattern 补充)</label>
<input type="email"
id="email2"
name="email_strict"
required
pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
title="请输入有效的邮箱地址,如 user@example.com"
placeholder="如 user@example.com">
<p class="hint">要求:标准邮箱格式,域名至少包含一个点号</p>
</div>
<!--
限制企业邮箱后缀
只允许以 @company.com 结尾的邮箱
-->
<div class="form-group">
<label for="email3">企业邮箱(仅限 company.com)</label>
<input type="email"
id="email3"
name="company_email"
required
pattern="^[a-zA-Z0-9._%+-]+@company\.com$"
title="请使用 company.com 的企业邮箱"
placeholder="如 zhangsan@company.com">
<p class="hint">仅接受 @company.com 结尾的企业邮箱</p>
</div>
<button type="submit">注册</button>
</form>
</body>
</html>与 datalist 配合
type="email" 也可以配合 list 属性和 <datalist> 提供邮箱建议:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>email 与 datalist</title>
</head>
<body>
<form action="/invite" method="post">
<label for="inviteEmail">邀请邮箱:</label>
<input type="email"
id="inviteEmail"
name="email"
list="knownEmails"
placeholder="输入或选择邮箱"
multiple>
<!-- 常用联系人邮箱列表 -->
<datalist id="knownEmails">
<option value="alice@example.com">
<option value="bob@example.com">
<option value="charlie@company.com">
<option value="david@company.com">
</datalist>
<button type="submit">发送邀请</button>
</form>
</body>
</html>验证 API 的使用
type="email" 的验证结果可以通过 JavaScript 的 Constraint Validation API 获取:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>email 验证 API</title>
</head>
<body>
<form id="emailForm">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required>
<button type="submit">提交</button>
</form>
<div id="result"></div>
<script>
const form = document.getElementById('emailForm');
const emailInput = document.getElementById('email');
const result = document.getElementById('result');
// 实时验证
emailInput.addEventListener('input', function() {
const validity = this.validity;
if (validity.valueMissing) {
result.textContent = '邮箱不能为空';
result.style.color = '#e74c3c';
} else if (validity.typeMismatch) {
result.textContent = '请输入有效的邮箱地址';
result.style.color = '#e74c3c';
} else if (this.value && validity.valid) {
result.textContent = '邮箱格式正确';
result.style.color = '#27ae60';
} else {
result.textContent = '';
}
});
// 提交验证
form.addEventListener('submit', function(e) {
e.preventDefault();
if (form.checkValidity()) {
result.textContent = '验证通过,准备提交:' + emailInput.value;
result.style.color = '#27ae60';
} else {
form.reportValidity();
}
});
</script>
</body>
</html>实战示例
带域后缀自动补全的邮箱输入
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>邮箱域后缀补全</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 500px;
margin: 40px auto;
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
font-weight: 500;
margin-bottom: 6px;
}
input {
width: 100%;
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 6px;
box-sizing: border-box;
font-size: 14px;
}
input:focus {
outline: none;
border-color: #4a90d9;
}
.suggestion-list {
list-style: none;
padding: 0;
margin: 4px 0 0;
border: 1px solid #ddd;
border-top: none;
border-radius: 0 0 6px 6px;
display: none;
max-height: 150px;
overflow-y: auto;
}
.suggestion-list.active {
display: block;
}
.suggestion-list li {
padding: 8px 12px;
cursor: pointer;
font-size: 14px;
}
.suggestion-list li:hover,
.suggestion-list li.highlighted {
background-color: #f0f7ff;
}
</style>
</head>
<body>
<h2>注册</h2>
<form action="/register" method="post">
<div class="form-group">
<label for="email">邮箱地址</label>
<div style="position: relative;">
<input type="email"
id="email"
name="email"
required
autocomplete="email"
placeholder="请输入邮箱">
<ul class="suggestion-list" id="suggestions"></ul>
</div>
</div>
<button type="submit">注册</button>
</form>
<script>
const emailInput = document.getElementById('email');
const suggestionList = document.getElementById('suggestions');
// 常见邮箱域名后缀
const domains = [
'qq.com', '163.com', '126.com', 'gmail.com',
'outlook.com', 'hotmail.com', 'yahoo.com',
'sina.com', 'foxmail.com', 'icloud.com'
];
emailInput.addEventListener('input', function() {
const value = this.value.trim();
suggestionList.innerHTML = '';
if (!value || value.includes('@')) {
suggestionList.classList.remove('active');
return;
}
// 生成建议列表
const fragment = document.createDocumentFragment();
domains.forEach(domain => {
const li = document.createElement('li');
li.textContent = value + '@' + domain;
li.addEventListener('mousedown', function(e) {
e.preventDefault();
emailInput.value = this.textContent;
suggestionList.classList.remove('active');
});
fragment.appendChild(li);
});
suggestionList.appendChild(fragment);
suggestionList.classList.add('active');
});
// 点击外部关闭建议列表
document.addEventListener('click', function(e) {
if (!e.target.closest('.form-group')) {
suggestionList.classList.remove('active');
}
});
// 失去焦点时延迟关闭(允许 mousedown 事件先执行)
emailInput.addEventListener('blur', function() {
setTimeout(() => {
suggestionList.classList.remove('active');
}, 200);
});
</script>
</body>
</html>注意事项
浏览器验证不检查邮箱是否存在:
type="email"只验证格式,不会验证邮箱地址是否真实存在或可以接收邮件。邮箱存在性检查需要通过服务器端发送验证邮件。pattern 验证比 type 验证更严格:如果同时设置了
type="email"和pattern,浏览器会先检查 pattern。pattern 的错误提示不会自动说明是邮箱格式问题,需要通过title属性补充说明。multiple 的提交格式:使用
multiple时,所有邮箱以逗号拼接成一个字符串。服务器端需要手动分割。移动端键盘因系统而异:iOS 和 Android 的邮箱键盘外观不同,但都包含
@和.快捷键。email 字段支持空值:如果未设置
required,空输入会通过验证。只有非空的值才会被检查邮箱格式。
最佳实践
使用
type="email"而非type="text":即使是简单的邮箱输入,也使用正确的 type,以获得自动验证和移动端优化。对于企业邮箱使用 pattern 限制后缀:如果只接受特定域名的邮箱,使用
pattern属性。为 email 设置
autocomplete="email":帮助浏览器正确保存和填充邮箱地址。不要过度限制 pattern:过于严格的正则可能拒绝合法的邮箱地址。浏览器默认的宽松验证通常是合理的选择。
服务器端验证是必须的:客户端验证可以被绕过,始终在服务器端验证邮箱格式和唯一性。
下一节
继续学习:number 数字输入