Skip to content

HTML 表单

什么是HTML表单

HTML表单是用于收集用户输入的重要工具,通过各种表单控件(如输入框、按钮、下拉菜单等)来获取用户数据,然后将数据提交到服务器进行处理。

基本表单结构

form 元素

html
<form action="/submit" method="POST">
    <!-- 表单控件 -->
</form>

表单属性

  • action: 表单提交的目标URL
  • method: 提交方法(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>

小结

  • 表单是收集用户输入的重要工具
  • 使用语义化的标签和适当的输入类型
  • 提供清晰的标签和帮助信息
  • 实现客户端和服务器端验证
  • 考虑可访问性和响应式设计
  • 优化用户体验,减少填写负担
  • 注意数据安全和隐私保护