<select>:HTML 选择元素

<select> HTML 元素表示提供选项菜单的控件。

¥The <select> HTML element represents a control that provides a menu of options.

Try it

上面的示例显示了典型的 <select> 用法。它被赋予一个 id 属性,使其能够与 <label> 关联以实现可访问性,以及一个 name 属性来表示提交给服务器的关联数据点的名称。每个菜单选项均由嵌套在 <select> 内的 <option> 元素定义。

¥The above example shows typical <select> usage. It is given an id attribute to enable it to be associated with a <label> for accessibility purposes, as well as a name attribute to represent the name of the associated data point submitted to the server. Each menu option is defined by an <option> element nested inside the <select>.

每个 <option> 元素都应该有一个 value 属性,其中包含选择该选项时要提交到服务器的数据值。如果不包含 value 属性,则该值默认为元素内包含的文本。你可以在 <option> 元素上包含 selected 属性,以使其在页面首次加载时默认被选中。

¥Each <option> element should have a value attribute containing the data value to submit to the server when that option is selected. If no value attribute is included, the value defaults to the text contained inside the element. You can include a selected attribute on an <option> element to make it selected by default when the page first loads.

<select> 元素有一些独特的属性,你可以使用它来控制它,例如 multiple 指定是否可以选择多个选项,size 指定一次应显示多少个选项。它还接受大多数通用表单输入属性,例如 requireddisabledautofocus 等。

¥The <select> element has some unique attributes you can use to control it, such as multiple to specify whether multiple options can be selected, and size to specify how many options should be shown at once. It also accepts most of the general form input attributes such as required, disabled, autofocus, etc.

你可以进一步将 <option> 元素嵌套在 <optgroup> 元素内,以在下拉列表中创建单独的选项组。你还可以包含 <hr> 元素来创建分隔符,在选项之间添加视觉分隔。

¥You can further nest <option> elements inside <optgroup> elements to create separate groups of options inside the dropdown. You can also include <hr> elements to create separators that add visual breaks between options.

有关更多示例,请参见 原生表单小部件:下拉内容

¥For further examples, see The native form widgets: Drop-down content.

属性

¥Attributes

该元素包括 全局属性

¥This element includes the global attributes.

autocomplete

提供 user agent's 自动补齐功能提示的字符串。有关如何使用自动补齐的值的完整列表和详细信息,请参阅 HTML 自动补齐属性

autofocus

此布尔属性允许你指定表单控件在页面加载时应具有输入焦点。文档中只能有一个表单元素具有 autofocus 属性。

disabled

此布尔属性指示用户无法与控件交互。如果未指定此属性,则控件将从包含元素继承其设置,例如 <fieldset>;如果不存在设置了 disabled 属性的包含元素,则启用该控件。

form

<select> 与其(其表单所有者)关联的 <form> 元素。该属性的值必须是同一文档中 <form>id。(如果未设置此属性,则 <select> 与其祖级 <form> 元素(如果有)相关联。)

此属性允许你在文档中的任何位置将 <select> 元素与 <form> 相关联,而不仅仅是在 <form> 内部。它还可以覆盖祖级 <form> 元素。

multiple

该布尔属性表示可以在列表中选择多个选项。如果未指定,则一次只能选择一个选项。当指定 multiple 时,大多数浏览器将显示滚动列表框而不是单行下拉列表。

name

该属性用于指定控件的名称。

required

布尔属性,指示必须选择具有非空字符串值的选项。

size

如果控件显示为滚动列表框(例如,指定 multiple 时),则此属性表示列表中应同时可见的行数。浏览器不需要将选择元素呈现为滚动列表框。默认值为 0

注意:根据 HTML 规范,size 的默认值应该是 1;然而,在实践中,我们发现这会破坏一些网站,并且目前没有其他浏览器能够做到这一点,因此 Mozilla 选择暂时继续在 Firefox 上返回 0

¥Note: According to the HTML specification, the default value for size should be 1; however, in practice, this has been found to break some websites, and no other browser currently does that, so Mozilla has opted to continue to return 0 for the time being with Firefox.

使用说明

¥Usage notes

选择多个选项

¥Selecting multiple options

在台式计算机上,有多种方法可以在具有 multiple 属性的 <select> 元素中选择多个选项:

¥On a desktop computer, there are a number of ways to select multiple options in a <select> element with a multiple attribute:

鼠标用户可以按住 CtrlCommandShift 键(具体取决于你的操作系统),然后单击多个选项来选择/取消选择它们。

¥Mouse users can hold the Ctrl, Command, or Shift keys (depending on what makes sense for your operating system) and then click multiple options to select/deselect them.

警告:下面描述的通过键盘选择多个不连续项目的机制目前似乎仅在 Firefox 中有效。

¥Warning: The mechanism for selecting multiple non-contiguous items via the keyboard described below currently only seems to work in Firefox.

在 macOS 上,Ctrl + UpCtrl + Down 快捷方式与任务控制和应用窗口的操作系统默认快捷方式冲突,因此你必须先将其关闭才能工作。

¥On macOS, the Ctrl + Up and Ctrl + Down shortcuts conflict with the OS default shortcuts for Mission Control and Application windows, so you'll have to turn these off before it will work.

键盘用户可以通过以下方式选择多个连续的项目:

¥Keyboard users can select multiple contiguous items by:

  • 专注于 <select> 元素(例如使用 Tab ).
  • 使用选择范围顶部或底部的项目 Up and Down 光标键可上下移动选项。
  • 按住 Shift 键,然后使用 Up and Down 光标键可增加或减少所选项目的范围。

键盘用户可以通过以下方式选择多个不连续的项目:

¥Keyboard users can select multiple non-contiguous items by:

  • 专注于 <select> 元素(例如使用 Tab ).
  • 按住 Ctrl 键,然后使用 Up and Down 光标键更改 "focused" 选择选项,即如果你选择这样做,将选择的选项。"focused" 选择选项以虚线轮廓高亮,与以键盘为中心的链接相同。
  • 紧迫 Space 选择/取消选择 "focused" 选择选项。

使用 CSS 设计样式

¥Styling with CSS

众所周知,<select> 元素很难用 CSS 高效地设置样式。你可以影响某些方面,如任何元素 - 例如,操纵 盒子模型显示字体 等,并且你可以使用 appearance 属性来删除默认系统 appearance

¥The <select> element is notoriously difficult to style productively with CSS. You can affect certain aspects like any element — for example, manipulating the box model, the displayed font, etc., and you can use the appearance property to remove the default system appearance.

但是,这些属性不会在浏览器之间产生一致的结果,并且很难执行诸如将不同类型的表单元素彼此排列在一列中之类的操作。<select> 元素内部结构复杂,难以控制。如果你想获得完全控制,你应该考虑使用具有良好设施的库来设置表单小部件的样式,或者尝试使用非语义元素、JavaScript 和 WAI-ARIA 滚动你自己的下拉菜单以提供语义。

¥However, these properties don't produce a consistent result across browsers, and it is hard to do things like line different types of form element up with one another in a column. The <select> element's internal structure is complex, and hard to control. If you want to get full control, you should consider using a library with good facilities for styling form widgets, or try rolling your own dropdown menu using non-semantic elements, JavaScript, and WAI-ARIA to provide semantics.

有关样式 <select> 的更多有用信息,请参阅:

¥For more useful information on styling <select>, see:

示例

¥Examples

基本选择

¥Basic select

以下示例创建一个非常简单的下拉菜单,默认选择第二个选项。

¥The following example creates a very simple dropdown menu, the second option of which is selected by default.

html
<!-- The second value will be selected initially -->
<select name="choice">
  <option value="first">First Value</option>
  <option value="second" selected>Second Value</option>
  <option value="third">Third Value</option>
</select>

结果

¥Result

使用分组选项进行选择

¥Select with grouping options

以下示例创建一个使用 <optgroup><hr> 分组的下拉菜单,以便用户更容易理解下拉菜单中的内容。

¥The following example creates a dropdown menu with grouping using <optgroup> and <hr> to make it easier for the user to understand the content in the dropdown.

html
<label for="hr-select">Your favorite food</label> <br />

<select name="foods" id="hr-select">
  <option value="">Choose a food</option>
  <hr />
  <optgroup label="Fruit">
    <option value="apple">Apples</option>
    <option value="banana">Bananas</option>
    <option value="cherry">Cherries</option>
    <option value="damson">Damsons</option>
  </optgroup>
  <hr />
  <optgroup label="Vegetables">
    <option value="artichoke">Artichokes</option>
    <option value="broccoli">Broccoli</option>
    <option value="cabbage">Cabbages</option>
  </optgroup>
  <hr />
  <optgroup label="Meat">
    <option value="beef">Beef</option>
    <option value="chicken">Chicken</option>
    <option value="pork">Pork</option>
  </optgroup>
  <hr />
  <optgroup label="Fish">
    <option value="cod">Cod</option>
    <option value="haddock">Haddock</option>
    <option value="salmon">Salmon</option>
    <option value="turbot">Turbot</option>
  </optgroup>
</select>

结果

¥Result

具有多种功能的高级选择

¥Advanced select with multiple features

以下示例更复杂,展示了可以在 <select> 元素上使用的更多功能:

¥The follow example is more complex, showing off more features you can use on a <select> element:

html
<label>
  Please choose one or more pets:
  <select name="pets" multiple size="4">
    <optgroup label="4-legged pets">
      <option value="dog">Dog</option>
      <option value="cat">Cat</option>
      <option value="hamster" disabled>Hamster</option>
    </optgroup>
    <optgroup label="Flying pets">
      <option value="parrot">Parrot</option>
      <option value="macaw">Macaw</option>
      <option value="albatross">Albatross</option>
    </optgroup>
  </select>
</label>

结果

¥Result

你会看到:

¥You'll see that:

  • 由于我们已包含 multiple 属性,因此可以选择多个选项。
  • size 属性导致一次只显示 4 行;你可以滚动查看所有选项。
  • 我们包含了 <optgroup> 元素来将选项分为不同的组。这是纯粹的视觉分组,其可视化通常包括粗体的组名称和缩进的选项。
  • "仓鼠" 选项包含 disabled 属性,因此根本无法选择。

自定义选择样式

¥Customizing select styles

此示例展示了如何使用一些 CSS 和 JavaScript 为 <select> 框提供广泛的自定义样式。

¥This example shows how you could use some CSS and JavaScript to provide extensive custom styling for a <select> box.

这个例子:

¥The example:

  • 在父封装器中克隆 <select> 的上下文(<option> 元素),并使用其他 HTML 元素和 JavaScript 重新实现标准预期行为。这包括提供键盘可访问性的基本选项卡行为。
  • 将新元素的一些标准原生 attributes 映射到 data-attributes,以便管理状态和 CSS。

注意:并非所有原生功能都受支持;这个例子是一个概念证明。它从标准 HTML 开始,但从 JSON 数据、自定义 HTML 或其他解决方案开始也可以实现相同的结果。

¥Note: Not all native features are supported; this example is a proof of concept. It starts from standard HTML but the same results could be achieved starting from JSON data, custom HTML, or other solutions.

HTML

html
<form>
  <section>
    <label for="select-standard">Standard controls:</label>
    <select name="1A" id="select-standard">
      <option>Carrots</option>
      <option>Peas</option>
      <option>Beans</option>
      <option>Pneumonoultramicroscopicsilicovolcanoconiosis</option>
    </select>
  </section>
  <hr />
  <section id="custom">
    <label for="select-custom">Custom controls:</label>
    <select name="2A" id="select-custom">
      <option>Carrots</option>
      <option>Peas</option>
      <option>Beans</option>
      <option>Pneumonoultramicroscopicsilicovolcanoconiosis</option>
    </select>
  </section>
</form>

CSS

css
body {
  font-family: Cambria, Cochin, Georgia, Times, "Times New Roman", serif;
  padding: 20px;
}

hr {
  margin: 20px 0;
}

label {
  margin-right: 10px;
}

.select:focus {
  border-color: blue;
}

.select[data-multiple] header {
  display: none;
}

.select div.header {
  content: "↓";
  display: flex;
  flex: 1;
  align-items: center;
  padding: 0;
  position: relative;
  width: auto;
  box-sizing: border-box;
  border-width: 1px;
  border-style: inherit;
  border-color: inherit;
  border-radius: inherit;
}

.select .header::after {
  content: "↓";
  align-self: stretch;
  display: flex;
  align-content: center;
  justify-content: center;
  justify-items: center;
  align-items: center;
  padding: 0.5em;
}

.select .header:hover::after {
  background-color: blue;
}

.select .header select {
  appearance: none;
  font-family: inherit;
  font-size: inherit;
  padding: 0;
  border-width: 0;
  width: 100%;
  flex: 1;
  display: none;
}

.select .header select optgroup {
  display: none;
}

.select select div.option {
  display: none;
}

.select {
  user-select: none;
  box-sizing: border-box;
  position: relative;
  border-radius: 4px;
  border-style: solid;
  border-width: 0;
  border-color: gray;
  width: auto;
  display: inline-block;
}

.select:focus,
.select:hover {
  border-color: blue;
}

.select[data-open] {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.select[data-open] datalist {
  display: initial;
}

.select datalist {
  appearance: none;
  position: absolute;
  border-style: solid;
  border-width: 1px;
  border-color: gray;
  left: 0;
  display: none;
  width: 100%;
  box-sizing: border-box;
  z-index: 2;
  border-bottom-left-radius: 4px;
  border-bottom-right-radius: 4px;
}

.select datalist .option {
  background-color: white;
  margin-bottom: 1px;
  cursor: pointer;
  padding: 0.5em;
  border-width: 0;
}

.select datalist .option:hover,
.select datalist .option:focus,
.select datalist .option:checked {
  background-color: blue;
  color: white;
}

.select .optgroup .option[data-disabled] {
  color: gray;
}

.select .optgroup .option[data-checked] {
  background-color: blue;
  color: white;
}

.select .optgroup .label {
  font-weight: bold;
}

.select .optgroup .option .label {
  font-weight: normal;
  padding: 0.25em;
}

.select .header span {
  flex: 1;
  padding: 0.5em;
}

JavaScript

js
const selects = custom.querySelectorAll("select");
for (const select of selects) {
  const div = document.createElement("div");
  const header = document.createElement("div");
  const datalist = document.createElement("datalist");
  const optgroups = select.querySelectorAll("optgroup");
  const span = document.createElement("span");
  const options = select.options;
  const parent = select.parentElement;
  const multiple = select.hasAttribute("multiple");
  function onclick(e) {
    const disabled = this.hasAttribute("data-disabled");
    select.value = this.dataset.value;
    span.innerText = this.dataset.label;
    if (disabled) return;
    if (multiple) {
      if (e.shiftKey) {
        const checked = this.hasAttribute("data-checked");
        if (checked) {
          this.removeAttribute("data-checked");
        } else {
          this.setAttribute("data-checked", "");
        }
      } else {
        const options = div.querySelectorAll(".option");
        for (let i = 0; i < options.length; i++) {
          const option = options[i];
          option.removeAttribute("data-checked");
        }
        this.setAttribute("data-checked", "");
      }
    }
  }

  function onkeyup(e) {
    e.preventDefault();
    e.stopPropagation();
    if (e.keyCode === 13) {
      this.click();
    }
  }

  div.classList.add("select");
  header.classList.add("header");
  div.tabIndex = 1;
  select.tabIndex = -1;
  span.innerText = select.label;
  header.appendChild(span);

  for (const attribute of select.attributes) {
    div.dataset[attribute.name] = attribute.value;
  }
  for (let i = 0; i < options.length; i++) {
    const option = document.createElement("div");
    const label = document.createElement("div");
    const o = options[i];
    for (const attribute of o.attributes) {
      option.dataset[attribute.name] = attribute.value;
    }
    option.classList.add("option");
    label.classList.add("label");
    label.innerText = o.label;
    option.dataset.value = o.value;
    option.dataset.label = o.label;
    option.onclick = onclick;
    option.onkeyup = onkeyup;
    option.tabIndex = i + 1;
    option.appendChild(label);
    datalist.appendChild(option);
  }
  div.appendChild(header);
  for (const o of optgroups) {
    const optgroup = document.createElement("div");
    const label = document.createElement("div");
    const options = o.querySelectorAll("option");

    Object.assign(optgroup, o);
    optgroup.classList.add("optgroup");
    label.classList.add("label");
    label.innerText = o.label;
    optgroup.appendChild(label);
    div.appendChild(optgroup);
    for (const o of options) {
      const option = document.createElement("div");
      const label = document.createElement("div");

      for (const attribute of o.attributes) {
        option.dataset[attribute.name] = attribute.value;
      }
      option.classList.add("option");
      label.classList.add("label");
      label.innerText = o.label;
      option.tabIndex = i + 1;
      option.dataset.value = o.value;
      option.dataset.label = o.label;
      option.onclick = onclick;
      option.onkeyup = onkeyup;
      option.tabIndex = i + 1;
      option.appendChild(label);
      optgroup.appendChild(option);
    }
  }

  div.onclick = (e) => {
    e.preventDefault();
  };

  parent.insertBefore(div, select);
  header.appendChild(select);
  div.appendChild(datalist);
  datalist.style.top = `${header.offsetTop + header.offsetHeight}px`;

  div.onclick = (e) => {
    if (!multiple) {
      const open = div.hasAttribute("data-open");
      e.stopPropagation();
      if (open) {
        div.removeAttribute("data-open");
      } else {
        div.setAttribute("data-open", "");
      }
    }
  };

  div.onkeyup = (event) => {
    event.preventDefault();
    if (event.keyCode === 13) {
      div.click();
    }
  };

  document.addEventListener("click", (e) => {
    if (div.hasAttribute("data-open")) {
      div.removeAttribute("data-open");
    }
  });

  const width = Math.max(
    ...Array.from(options).map((e) => {
      span.innerText = e.label;
      return div.offsetWidth;
    }),
  );

  console.log(width);
  div.style.width = `${width}px`;
}
document.forms[0].onsubmit = (e) => {
  const data = new FormData(this);
  e.preventDefault();
  submit.innerText = JSON.stringify([...data.entries()]);
};

结果

¥Result

无障碍问题

¥Accessibility concerns

<select> 中的 <hr> 应被视为纯粹的装饰性,因为它们目前未暴露在可访问性树中,因此未暴露于辅助技术。

¥The <hr> within a <select> should be considered purely decorative, as they are currently not exposed within the accessibility tree and therefore not exposed to assistive technologies.

技术总结

¥Technical summary

内容类别 流量内容措辞内容互动内容listedlabelableresettablesubmittable form-associated 元素
允许的内容 零个或多个 <option><optgroup><hr> 元素。
标签遗漏 无,开始和结束标记都是强制性的。
允许的父级 任何接受 措辞内容 的元素。
隐式 ARIA 角色 combobox multiple 属性且 size 属性大于 1,否则 listbox
允许的 ARIA 角色 menu multiple 属性和 size 属性大于 1,否则不允许 role
DOM 接口 HTMLSelectElement

规范

Specification
HTML Standard
# the-select-element

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看

¥See also