<input type="radio">

Baseline 已广泛支持

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

<input> 元素的 radio 类型通常用于单选按钮组——描述一组相关选项的单选按钮集合。

在给定的单选按钮组中,一次只能选择一个单选按钮。单选按钮通常呈现为小圆圈,选中时会被填充或高亮。

试一试

<fieldset>
  <legend>Select a maintenance drone:</legend>

  <div>
    <input type="radio" id="huey" name="drone" value="huey" checked />
    <label for="huey">Huey</label>
  </div>

  <div>
    <input type="radio" id="dewey" name="drone" value="dewey" />
    <label for="dewey">Dewey</label>
  </div>

  <div>
    <input type="radio" id="louie" name="drone" value="louie" />
    <label for="louie">Louie</label>
  </div>
</fieldset>
p,
label {
  font:
    1rem "Fira Sans",
    sans-serif;
}

input {
  margin: 0.4rem;
}

它们之所以被称为单选按钮(radio buttons),是因为其外观和操作方式与老式收音机上的按钮类似,如下图所示。

Shows what radio buttons looked like in the olden days.

备注: 复选框与单选按钮类似,但有一个重要的区别:单选按钮用于从一组选项中选择一个值,而复选框允许你打开或关闭单个值。当有多个控件时,单选按钮允许从中选择一个,而复选框允许多个值被选中。

value 属性是一个包含单选按钮值的字符串。该值永远不会被用户代理显示给用户。相反,它用于标识一个组中哪个单选按钮被选中。

定义一个单选按钮组

通过为组中的每个单选按钮指定相同的 name 来定义一个单选按钮组。一旦建立了单选按钮组,选中该组中的任何一个单选按钮,都会自动取消选中同一组中任何当前已选中的单选按钮。

你可以在一个页面上设置任意数量的单选按钮组,只要每个组都有自己唯一的 name

例如,如果你的表单需要询问用户的首选联系方式,你可以创建三个单选按钮,每个按钮的 name 属性都设置为 contact,但一个的 value 为 email,一个为 phone,另一个为 mail。用户永远不会看到 valuename(除非你明确添加代码来显示它们)。

最终的 HTML 如下所示

html
<form>
  <fieldset>
    <legend>Please select your preferred contact method:</legend>
    <div>
      <input type="radio" id="contactChoice1" name="contact" value="email" />
      <label for="contactChoice1">Email</label>

      <input type="radio" id="contactChoice2" name="contact" value="phone" />
      <label for="contactChoice2">Phone</label>

      <input type="radio" id="contactChoice3" name="contact" value="mail" />
      <label for="contactChoice3">Mail</label>
    </div>
    <div>
      <button type="submit">Submit</button>
    </div>
  </fieldset>
</form>

在这里,你可以看到三个单选按钮,每个按钮的 name 都设置为 contact,并且每个按钮都有一个唯一的 value,用于唯一标识该组中的单个单选按钮。它们每个也都有一个唯一的 id<label> 元素的 for 属性会使用它来将标签与单选按钮关联起来。

你可以在这里试用这个例子

单选按钮组的数据表示

当上述表单在选中一个单选按钮后提交时,表单的数据会包含一个格式为 contact=value 的条目。例如,如果用户点击“电话”单选按钮然后提交表单,表单的数据将包含 contact=phone 这一行。

如果你在 HTML 中省略了 value 属性,提交的表单数据会为该组分配值 on。在这种情况下,如果用户点击了“电话”选项并提交表单,得到的表单数据将是 contact=on,这没什么用。所以不要忘记设置你的 value 属性!

备注: 如果在提交表单时没有选中任何单选按钮,那么该单选按钮组将完全不包含在提交的表单数据中,因为没有值可以报告。

允许在未选择任何单选按钮组中的按钮的情况下提交表单的情况相当少见,所以通常明智的做法是让其中一个默认处于 checked 状态。请参阅下面的默认选中一个单选按钮

让我们在我们的例子中添加一些代码,以便我们可以检查这个表单生成的数据。HTML 被修改为添加一个 <pre> 块,用于输出表单数据

html
<form>
  <fieldset>
    <legend>Please select your preferred contact method:</legend>
    <div>
      <input type="radio" id="contactChoice1" name="contact" value="email" />
      <label for="contactChoice1">Email</label>
      <input type="radio" id="contactChoice2" name="contact" value="phone" />
      <label for="contactChoice2">Phone</label>
      <input type="radio" id="contactChoice3" name="contact" value="mail" />
      <label for="contactChoice3">Mail</label>
    </div>
    <div>
      <button type="submit">Submit</button>
    </div>
  </fieldset>
</form>
<pre id="log"></pre>

然后我们添加一些 JavaScript 来在 submit 事件上设置一个事件监听器,当用户点击“提交”按钮时会发送该事件

js
const form = document.querySelector("form");
const log = document.querySelector("#log");

form.addEventListener("submit", (event) => {
  const data = new FormData(form);
  let output = "";
  for (const entry of data) {
    output = `${output}${entry[0]}=${entry[1]}\r`;
  }
  log.innerText = output;
  event.preventDefault();
});

试试这个例子,看看 contact 组的结果永远不会超过一个。

附加属性

除了所有 <input> 元素共享的通用属性外,radio 类型的输入框还支持以下属性。

checked

一个布尔属性,如果存在,表示该单选按钮是组中的默认选中项。

与其他浏览器不同,Firefox 默认会在页面加载时保留 <input> 的动态选中状态。使用 autocomplete 属性来控制此功能。

value

value 属性是所有 <input> 共享的属性;然而,它对于类型为 radio 的输入框有特殊用途:当表单提交时,只有当前被选中的单选按钮会被提交到服务器,并且报告的值是 value 属性的值。如果 value 没有另外指定,它默认为字符串 on。这在上面的一节中有演示。

required

required 属性是大多数 <input> 共享的属性。如果一个同名单选按钮组中的任何一个单选按钮有 required 属性,那么该组中必须有一个单选按钮被选中,尽管不一定是应用了该属性的那个。

使用单选输入框

我们已经介绍了单选按钮的基础知识。现在让我们看看你可能需要了解的其他常见的与单选按钮相关的特性和技术。

默认选中一个单选按钮

要让一个单选按钮默认被选中,你需要包含 checked 属性,如前面例子的修订版所示

html
<form>
  <fieldset>
    <legend>Please select your preferred contact method:</legend>
    <div>
      <input
        type="radio"
        id="contactChoice1"
        name="contact"
        value="email"
        checked />
      <label for="contactChoice1">Email</label>

      <input type="radio" id="contactChoice2" name="contact" value="phone" />
      <label for="contactChoice2">Phone</label>

      <input type="radio" id="contactChoice3" name="contact" value="mail" />
      <label for="contactChoice3">Mail</label>
    </div>
    <div>
      <button type="submit">Submit</button>
    </div>
  </fieldset>
</form>

在这种情况下,第一个单选按钮现在是默认选中的。

备注: 如果你将 checked 属性放在多个单选按钮上,后面的实例会覆盖前面的实例;也就是说,最后一个带有 checked 的单选按钮将被选中。这是因为一个组中一次只能有一个单选按钮被选中,并且每当一个新的按钮被标记为选中时,用户代理会自动取消选中其他按钮。

为你的单选按钮提供更大的点击区域

在上面的例子中,你可能已经注意到,你可以通过点击其关联的 <label> 元素以及单选按钮本身来选择一个单选按钮。这是 HTML 表单标签一个非常有用的特性,它使用户更容易点击他们想要的选项,尤其是在像智能手机这样的小屏幕设备上。

除了可访问性之外,这也是在你的表单上正确设置 <label> 元素的另一个好理由。

验证

对于设置了 required 属性的单选按钮,或者一个同名单选按钮组中至少有一个成员设置了 required,那么必须有一个单选按钮被选中,该控件才被认为是有效的。如果没有单选按钮被选中,在验证期间 ValidityState 对象的 valueMissing 属性将返回 true,浏览器会要求用户选择一个选项。

为单选输入框设置样式

下面的例子展示了我们在本文中看到的例子的一个稍微更详尽的版本,带有一些额外的样式,并通过使用专门的元素建立了更好的语义。HTML 如下所示

html
<form>
  <fieldset>
    <legend>Please select your preferred contact method:</legend>
    <div>
      <input
        type="radio"
        id="contactChoice1"
        name="contact"
        value="email"
        checked />
      <label for="contactChoice1">Email</label>

      <input type="radio" id="contactChoice2" name="contact" value="phone" />
      <label for="contactChoice2">Phone</label>

      <input type="radio" id="contactChoice3" name="contact" value="mail" />
      <label for="contactChoice3">Mail</label>
    </div>
    <div>
      <button type="submit">Submit</button>
    </div>
  </fieldset>
</form>

这个例子中涉及的 CSS 要多一些

css
html {
  font-family: sans-serif;
}

div:first-of-type {
  display: flex;
  align-items: flex-start;
  margin-bottom: 5px;
}

label {
  margin-right: 15px;
  line-height: 32px;
}

input {
  appearance: none;

  border-radius: 50%;
  width: 16px;
  height: 16px;

  border: 2px solid #999999;
  transition: 0.2s all linear;
  margin-right: 5px;

  position: relative;
  top: 4px;
}

input:checked {
  border: 6px solid black;
}

button,
legend {
  color: white;
  background-color: black;
  padding: 5px 10px;
  border-radius: 0;
  border: 0;
  font-size: 14px;
}

button:hover,
button:focus {
  color: #999999;
}

button:active {
  background-color: white;
  color: black;
  outline: 1px solid black;
}

这里最值得注意的是 appearance 属性的使用(需要前缀以支持某些浏览器)。默认情况下,单选按钮(和复选框)会使用操作系统的原生样式来渲染这些控件。通过指定 appearance: none,你可以完全移除原生样式,并为它们创建自己的样式。在这里,我们使用 borderborder-radiustransition 来创建一个漂亮的动画单选效果。还要注意 :checked 伪类是如何被用来指定单选按钮被选中时的外观样式的。

备注: 如果你希望使用 appearance 属性,你应该非常仔细地测试它。虽然它在大多数现代浏览器中都得到支持,但其实现方式差异很大。在旧版浏览器中,即使是关键字 none 在不同浏览器中的效果也不尽相同,有些浏览器根本不支持它。在最新的浏览器中,差异较小。

请注意,当点击一个单选按钮时,随着两个按钮状态的改变,会有一个平滑的淡出/淡入效果。此外,图例和提交按钮的样式和颜色被定制为具有强烈的对比度。这可能不是你在真实 Web 应用中想要的外观,但它确实展示了各种可能性。

技术摘要

一个表示单选按钮值的字符串。
事件 changeinput
支持的常见属性 checkedvaluerequired
IDL 属性 checkedvalue
DOM 接口 HTMLInputElement
方法 select()
隐式 ARIA 角色 radio

规范

规范
HTML
# radio-button-state-(type=radio)

浏览器兼容性

另见