Appearance
HTML 表单
什么是HTML表单
HTML表单是用于收集用户输入的重要工具,通过各种表单控件(如输入框、按钮、下拉菜单等)来获取用户数据,然后将数据提交到服务器进行处理。
基本表单结构
form 元素
html
<form action="/submit" method="POST">
<!-- 表单控件 -->
</form>表单属性
action: 表单提交的目标URLmethod: 提交方法(GET或POST)enctype: 编码类型target: 打开方式
基本输入控件
文本输入
html
<form>
<!-- 单行文本 -->
<label for="username">用户名:</label>
<input type="text" id="username" name="username" placeholder="请输入用户名" required>
<!-- 密码 -->
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
<!-- 邮箱 -->
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" placeholder="user@example.com">
<!-- 多行文本 -->
<label for="message">留言:</label>
<textarea id="message" name="message" rows="4" cols="50" placeholder="请输入您的留言"></textarea>
</form>选择控件
html
<form>
<!-- 单选按钮 -->
<fieldset>
<legend>性别</legend>
<label>
<input type="radio" name="gender" value="male"> 男
</label>
<label>
<input type="radio" name="gender" value="female"> 女
</label>
</fieldset>
<!-- 复选框 -->
<fieldset>
<legend>兴趣爱好</legend>
<label>
<input type="checkbox" name="hobbies" value="reading"> 读书
</label>
<label>
<input type="checkbox" name="hobbies" value="music"> 音乐
</label>
<label>
<input type="checkbox" name="hobbies" value="sports"> 运动
</label>
</fieldset>
<!-- 下拉菜单 -->
<label for="city">城市:</label>
<select id="city" name="city">
<option value="">请选择城市</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
<option value="shenzhen">深圳</option>
</select>
<!-- 多选下拉 -->
<label for="skills">技能:</label>
<select id="skills" name="skills" multiple>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="javascript">JavaScript</option>
<option value="python">Python</option>
</select>
</form>数字和日期输入
html
<form>
<!-- 数字输入 -->
<label for="age">年龄:</label>
<input type="number" id="age" name="age" min="1" max="120" step="1">
<!-- 范围输入 -->
<label for="volume">音量:</label>
<input type="range" id="volume" name="volume" min="0" max="100" step="1" value="50">
<!-- 日期输入 -->
<label for="birthday">生日:</label>
<input type="date" id="birthday" name="birthday">
<!-- 时间输入 -->
<label for="meeting-time">会议时间:</label>
<input type="datetime-local" id="meeting-time" name="meeting-time">
<!-- 颜色选择 -->
<label for="color">喜欢的颜色:</label>
<input type="color" id="color" name="color" value="#007acc">
</form>完整表单示例
用户注册表单
html
<style>
.registration-form {
max-width: 600px;
margin: 0 auto;
padding: 30px;
background: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #333;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 10px;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 16px;
transition: border-color 0.3s ease;
box-sizing: border-box;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: #007acc;
}
.checkbox-group,
.radio-group {
display: flex;
gap: 15px;
margin-top: 10px;
}
.checkbox-group label,
.radio-group label {
display: flex;
align-items: center;
font-weight: normal;
cursor: pointer;
}
.checkbox-group input,
.radio-group input {
width: auto;
margin-right: 8px;
}
.submit-btn {
background-color: #007acc;
color: white;
padding: 12px 30px;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.submit-btn:hover {
background-color: #005fa3;
}
.required {
color: red;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
}
@media (max-width: 768px) {
.form-row {
grid-template-columns: 1fr;
}
.checkbox-group,
.radio-group {
flex-direction: column;
gap: 10px;
}
}
</style>
<form class="registration-form" action="/register" method="POST">
<h2>用户注册</h2>
<div class="form-row">
<div class="form-group">
<label for="firstName">姓 <span class="required">*</span></label>
<input type="text" id="firstName" name="firstName" required>
</div>
<div class="form-group">
<label for="lastName">名 <span class="required">*</span></label>
<input type="text" id="lastName" name="lastName" required>
</div>
</div>
<div class="form-group">
<label for="email">邮箱地址 <span class="required">*</span></label>
<input type="email" id="email" name="email" placeholder="user@example.com" required>
</div>
<div class="form-group">
<label for="password">密码 <span class="required">*</span></label>
<input type="password" id="password" name="password" minlength="6" required>
</div>
<div class="form-group">
<label for="confirmPassword">确认密码 <span class="required">*</span></label>
<input type="password" id="confirmPassword" name="confirmPassword" required>
</div>
<div class="form-group">
<label for="phone">手机号码</label>
<input type="tel" id="phone" name="phone" placeholder="13800138000">
</div>
<div class="form-group">
<label for="birthday">出生日期</label>
<input type="date" id="birthday" name="birthday">
</div>
<div class="form-group">
<label>性别</label>
<div class="radio-group">
<label>
<input type="radio" name="gender" value="male"> 男
</label>
<label>
<input type="radio" name="gender" value="female"> 女
</label>
<label>
<input type="radio" name="gender" value="other"> 其他
</label>
</div>
</div>
<div class="form-group">
<label for="city">所在城市</label>
<select id="city" name="city">
<option value="">请选择城市</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
<option value="shenzhen">深圳</option>
<option value="other">其他</option>
</select>
</div>
<div class="form-group">
<label>兴趣爱好</label>
<div class="checkbox-group">
<label>
<input type="checkbox" name="hobbies" value="reading"> 阅读
</label>
<label>
<input type="checkbox" name="hobbies" value="music"> 音乐
</label>
<label>
<input type="checkbox" name="hobbies" value="sports"> 运动
</label>
<label>
<input type="checkbox" name="hobbies" value="travel"> 旅游
</label>
</div>
</div>
<div class="form-group">
<label for="bio">个人简介</label>
<textarea id="bio" name="bio" rows="4" placeholder="简单介绍一下自己..."></textarea>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="agreement" value="1" required>
我已阅读并同意 <a href="#">用户协议</a> 和 <a href="#">隐私政策</a> <span class="required">*</span>
</label>
</div>
<div class="form-group">
<button type="submit" class="submit-btn">注册账户</button>
</div>
</form>表单验证
HTML5 内置验证
html
<form>
<!-- 必填字段 -->
<input type="text" name="username" required>
<!-- 长度限制 -->
<input type="text" name="name" minlength="2" maxlength="20">
<!-- 数值范围 -->
<input type="number" name="age" min="18" max="100">
<!-- 正则表达式验证 -->
<input type="text" name="phone" pattern="[0-9]{11}" title="请输入11位手机号">
<!-- 自定义验证消息 -->
<input type="email" name="email" required oninvalid="this.setCustomValidity('请输入正确的邮箱格式')" oninput="this.setCustomValidity('')">
</form>自定义验证样式
html
<style>
.form-field {
margin-bottom: 20px;
}
.form-field input {
width: 100%;
padding: 10px;
border: 2px solid #ddd;
border-radius: 5px;
}
.form-field input:valid {
border-color: #28a745;
}
.form-field input:invalid {
border-color: #dc3545;
}
.form-field input:focus {
outline: none;
box-shadow: 0 0 5px rgba(0, 122, 204, 0.5);
}
.error-message {
color: #dc3545;
font-size: 14px;
margin-top: 5px;
display: none;
}
.form-field input:invalid + .error-message {
display: block;
}
</style>
<form>
<div class="form-field">
<label>邮箱地址:</label>
<input type="email" name="email" required>
<div class="error-message">请输入有效的邮箱地址</div>
</div>
<div class="form-field">
<label>密码:</label>
<input type="password" name="password" minlength="8" required>
<div class="error-message">密码至少需要8个字符</div>
</div>
</form>高级表单控件
文件上传
html
<style>
.file-upload {
position: relative;
display: inline-block;
cursor: pointer;
background-color: #007acc;
color: white;
padding: 10px 20px;
border-radius: 5px;
transition: background-color 0.3s;
}
.file-upload:hover {
background-color: #005fa3;
}
.file-upload input[type="file"] {
position: absolute;
left: -9999px;
}
.file-info {
margin-top: 10px;
font-size: 14px;
color: #666;
}
</style>
<form enctype="multipart/form-data">
<div class="form-group">
<label>上传头像:</label>
<div class="file-upload">
<input type="file" id="avatar" name="avatar" accept="image/*" onchange="showFileName(this)">
选择文件
</div>
<div id="file-info" class="file-info">未选择文件</div>
</div>
<div class="form-group">
<label>上传文档:</label>
<input type="file" name="documents" multiple accept=".pdf,.doc,.docx">
</div>
</form>
<script>
function showFileName(input) {
const fileInfo = document.getElementById('file-info');
if (input.files.length > 0) {
fileInfo.textContent = `已选择: ${input.files[0].name}`;
} else {
fileInfo.textContent = '未选择文件';
}
}
</script>搜索和数据列表
html
<form>
<div class="form-group">
<label for="search">搜索:</label>
<input type="search" id="search" name="search" placeholder="输入搜索关键词">
</div>
<div class="form-group">
<label for="browser">选择浏览器:</label>
<input list="browsers" id="browser" name="browser" placeholder="输入或选择浏览器">
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
<option value="Opera">
</datalist>
</div>
</form>表单布局技巧
响应式表单
html
<style>
.responsive-form {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
.form-group-full {
grid-column: 1 / -1;
}
@media (max-width: 600px) {
.form-grid {
grid-template-columns: 1fr;
}
}
</style>
<form class="responsive-form">
<h2>联系我们</h2>
<div class="form-grid">
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="phone">电话:</label>
<input type="tel" id="phone" name="phone">
</div>
<div class="form-group">
<label for="company">公司:</label>
<input type="text" id="company" name="company">
</div>
<div class="form-group form-group-full">
<label for="subject">主题:</label>
<input type="text" id="subject" name="subject" required>
</div>
<div class="form-group form-group-full">
<label for="message">消息:</label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<div class="form-group form-group-full">
<button type="submit" class="submit-btn">发送消息</button>
</div>
</div>
</form>表单可访问性
标签和描述
html
<form>
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" aria-describedby="username-help" required>
<div id="username-help" class="help-text">用户名必须是3-20个字符</div>
</div>
<fieldset>
<legend>联系方式</legend>
<div class="form-group">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" aria-required="true">
</div>
<div class="form-group">
<label for="phone">电话:</label>
<input type="tel" id="phone" name="phone">
</div>
</fieldset>
<div role="group" aria-labelledby="notification-legend">
<div id="notification-legend">通知设置:</div>
<label>
<input type="checkbox" name="notifications" value="email">
邮件通知
</label>
<label>
<input type="checkbox" name="notifications" value="sms">
短信通知
</label>
</div>
</form>常见错误
1. 缺少标签关联
html
<!-- 错误 -->
<label>用户名</label>
<input type="text" name="username">
<!-- 正确 -->
<label for="username">用户名</label>
<input type="text" id="username" name="username">2. 不合理的输入类型
html
<!-- 错误 -->
<input type="text" placeholder="请输入邮箱">
<!-- 正确 -->
<input type="email" placeholder="请输入邮箱">3. 缺少表单验证
html
<!-- 错误 -->
<input type="email" name="email">
<!-- 正确 -->
<input type="email" name="email" required aria-describedby="email-error">
<div id="email-error" class="error-message"></div>小结
- 表单是收集用户输入的重要工具
- 使用语义化的标签和适当的输入类型
- 提供清晰的标签和帮助信息
- 实现客户端和服务器端验证
- 考虑可访问性和响应式设计
- 优化用户体验,减少填写负担
- 注意数据安全和隐私保护