3.8 HTML 表单(Forms)

表单是HTML最主要的用户输入元素

用户和网页的交互动作有鼠标悬停、点击链接(或移动触摸)和页面滚动等,这些交互方式一般只是服务器单向信息输出

有时候用户需要输入一些信息给服务器来完成双向交互,这类交互包括:

  • 注册/登录
  • 用户信息填写
  • 搜索/过滤
  • 上传文件
  • 文章编辑

表单及其控件就是HTML用来支持上述交互的主要元素:

  • 文本输入(单行或多行)
  • 单选框
  • 多选框
  • 下拉列表
  • 文件上传控件
  • 表单提交按钮

这些控件使用不同的HTML 标签,但大部分使用 <input> 标签,而使用 type 属性来区别输入控件的类型:

<!-- 文本输入 -->
<input type="text">
<!-- 复选框 -->
<input type="checkbox">
<!-- 单选框 -->
<input type="radio">


表单元素(form)

<form> 是块级元素,用来定义网页中的交互输入部分。所有的表单控件必须包含在 <form> 元素中。

表单元素有两个必须的属性:

  • action 用来定义信息提交的目标(即表单提交到哪里去)
  • method 用来定义信息提交的方式(即表单怎么提交),可以是 GET 或 POST 其中之一。

通常表单信息被提交给 action 所指定的服务器程序,服务器(即后端程序如PHP/Java)会对表单信息做出处理并给出应答。

表单用来把一组表单控件集中起来完成一个特定的交互操作,比如登录表单,通常包含3个控件:

  • 电子邮箱 <input type="email">
  • 用户密码 <input type="password">
  • 提交按钮 <input type="submit">

这些控件被包含在一个 <form action="/login" method="POST"> 元素中。

文本输入框

为了支持用户输入姓名,电子邮件,密码,地址等信息,HTML表单中的文本输入框控件包含多种类型:

普通文本 <input type="text"> 可以输入任意字符
电子邮件 <input type="email"> 如果输入的是非法电子邮件,会出现告警提示
密码 <input type="password"> 显示为小黑点,隐藏用户输入
数字 <input type="number"> 只能输入数字,且可以使用上下键来快速改变数值
电话 <input type="tel"> 可以触发自动填充
多行文本 <textarea></textarea> 可以调整文本输入框的大小

尽管这些输入框看起来很相似,且数据类型的默认校验也不那么有效,似乎有点冗余,但从语义上来看,type 赋予了输入框更具体的含义,这会有助于浏览器在实现这些控件接口时更好的提升用户交互体验。

占位符(Placeholders)

为了更好的提示用户输入,文本输入框可以显示占位符文本而不是空白,占位符在用户开始输入时会自动消失,不会形成干扰。

<input type="text" placeholder="请输入昵称">

试一下,当你开始输入时,“请输入昵称” 会消失。

标签(Labels)

由于表单控件本身不具备很好的自描述性,通常会在控件前面添加配对的文本标签(label),对控件作用做出提示。

<label>Email</label>
<input type="email">

对于纯文本输入框而言标签(label)和占位符(placeholder)功能类似,不过标签会一直显示,且可以用于保持和其它表单元素对齐,比如选择框。

尽管我们可以使用简短的文本来描述表单控件,使用 <label> 在语义上要更符合规范,它们只用于表单内,还可以通过 for 属性来和拥有特定 id 的输入控件配对使用。

<label for="first_name">名字</label>
<input id="first_name" type="text">

点击标签文本,输入焦点会移动到文本输入框内。这对于单选和复选框的操作尤为方便。

复选框(Checkboxes)

复选框 是选择型控件,拥有两个状态:选中(checked)和未选中(unchecked)。一般用来接受用户回答“是”或“否”。

<input type="checkbox"> 同意用户协议
同意用户协议

由于选择框很小,点击选中不方便,因此,比较好的实践是在该元素外面包裹一个 <label>

<label>
  <input type="checkbox"> 同意用户协议
</label>

除了上面的方法,也可以使用label的 <for> 属性来和input配对:

<input id="terms" type="checkbox">
<label for="terms">同意用户协议</label>

这样你就可以通过点击 “同意用户协议” 来切换复选框的选择状态。

默认情况下,复选框是未选中状态,你可以简单的通过设置 checked 属性来改变状态。

<label>
  <input type="checkbox" checked> 同意用户协议
</label>

复选框还有一个重要的用途是可以让用户在一组可选项中进行多项选择

首先我们需要组合(group)一些复选框,为此我们为它们设置相同的 name 属性:


<label>兴趣</label>
<input id="game" type="checkbox" name="interests">
<label for="game">电竞</label>
<input id="coding" type="checkbox" name="interests">
<label for="coding">编码</label>
<input id="rock" type="checkbox" name="interests">
<label for="rock">摇滚</label>

单选框(Radioboxes)

单选框用来给用户在一组可选项中做单项选择

同上,我们通过为单选框设置相同的 name 属性来把它们编组:

<label>婚姻状态</label>
<label>
  <input type="radio" name="status">
  单身
</label>
<label>
  <input type="radio" name="status">
  已婚
</label>
<label>
  <input type="radio" name="status">
  离异
</label>

由于我们把这组单选框的 name 属性都设置成了相同的 "status",选择其中一项,将导致其它选项被重置为未选中状态。这就是单选框的互斥(mutually exclusive)特性。

单选框和复选框的差异

复选框可以只有一个,用于提示用户回答是或否。而单个的单选框却没有意义,必须是一组可选项(至少2个),用于多选1。

此外,你可以不点击任何的单选框,但是你必须点击来选择一个单选框,且你无法通过再次点击同一个单选框来让它处于未选中状态,你只有通过选择一组单选框中的其他兄弟选项来重置之前的状态。

对于少量的选项,单选框和复选框已经可以满足要求,但是如果选项很多时,从界面布局以及可扩展性的角度而言,选择框是受到空间限制的。 而且对于大量的选项,我们还需要提供选项过滤功能以便快速定位选项,因此在这种情况下,我们需要使用新的表单界面组件: <select> 下拉列表框。 该控件通过滚动条和接受键盘输入事件的界面设计无限扩展了选项可用空间。

下拉列表框同时支持单项或多项选择,下面是月份选择的下拉列表框控件:

<select>
  <option>January</option>
  <option>February</option>
  <option>March</option>
  <option>April</option>
  <option>May</option>
  <option>June</option>
  <option>July</option>
  <option>August</option>
  <option>September</option>
  <option>October</option>
  <option>November</option>
  <option>December</option>
</select>

你可以试着输入字母S,将很快定位到September选项,类似的,如果连续输入May字符串,将直接定位到May选项。这大大加快了选项检索过程。

上面的列表你只能选择一个选项,要想选择多个选项,可以通过设置 multiple 属性:

<label>浏览器兼容性:</label>
<select multiple>
  <option>Google Chrome</option>
  <option>Internet Explorer</option>
  <option>Mozilla Firefox</option>
  <option>Opera</option>
  <option>Safari</option>
</select>

按住Ctrl(或⌘)键,然后点击多个选项。重复点击即取消之前的选项。

我们还可以使用<optgroup>给下拉列表框中的选项进行分组,这样就能形成类似树形的分级选择控件。

下面给出一个完整包含上述各个元素的表单实例:

为了布局的美观,使用了CSS样式,也就是接下来我们要讲解的课程内容。