请求开发者反馈:可自定义选择

多年来,为 <select> 元素等表单控件设置样式一直被视为开发者的主要痛点,我们一直在努力寻找解决方案。虽然这项工作很复杂,需要很长时间才能做好,但我们已经非常接近推出这项功能了。可自定义版本的 select 元素已正式进入 WHATWG 的第 2 阶段,引起了跨浏览器的强烈兴趣,并且您可以通过 Chrome Canary 版 130 测试原型。

欢迎试用并向我们提供反馈

检查您安装的 Chrome Canary 版 是否已更新到版本 130,以及您是否已开启实验性 Web 平台功能标志。如需开启此标志,请在地址栏中前往 chrome://flags,然后开启 #experimental-web-platform-features。然后,您应该就能看到本文中的 Codepen 演示。或者,您也可以查看此 Codepen 集合,在一个位置查看所有这些示例。

请使用此表单提供有关该功能的反馈。只需 3 分钟即可完成!

让我们深入了解可自定义的 select API 的功能,该 API 基于现有的 HTML select 标记构建。

选择启用新版 <select>

如需选择启用新行为,请在页内选择按钮和选择器上使用 CSS appearance 属性。如需选择启用,请在 <select> 元素和 ::picker(select) 上设置 appearance: base-select。

::picker(select) 是用户代理提供的新伪元素,仅适用于已使用 appearance: base-select 选择采用新行为的 <select> 元素。此选择器伪元素是由基本选择按钮触发的弹出式窗口。您可以选择同时启用这两项功能,如以下代码所示:

select,
::picker(select) {
  appearance: base-select;
}

您可以选择仅启用页面内按钮,但不能仅启用选择器弹出式窗口而不启用页面内按钮。只有在将 appearance: base-select 应用于 <select> 后,系统才会创建 ::picker(select)。

现在,您可以自定义 select 元素了。新的可自定义选择框自带一些默认样式,这些样式在不同浏览器和操作系统中看起来都一样。以下是 macOS 上的 Chrome 中默认自定义选择与现有选择的对比:

右侧可自定义选择框的默认用户代理样式。此功能可能会发生变化,我们非常期待收到您的反馈。
基本 select 与可自定义 select 的演示。

拆解各部分

显示选择器各个部分的示意图。

进入新的可自定义选择模式后,您现在可以访问的新元素包括: - selectedoption:反映当前所选选项的内部 HTML。 - option::before:包含一个对勾标记,用于指示当前所选选项作为默认无障碍功能(可能会发生变化)。 - ::picker(select):包含可自定义选择框内 button 之外的所有内容的弹出式窗口。

您可以为选择器的任何部分设置样式。例如,您可以在 <option> 元素中添加任意非互动内容,为打开下拉菜单的页内按钮设置样式,以及为选项下拉列表 (::picker(select)) 设置样式。

您还可以设置 button 的样式、自带箭头指示器,并在任何元素内部和周围添加任意内容。除了添加内容之外,您还可以隐藏这些新元素和默认样式。例如,如果您不希望在选项的 ::before 伪元素中显示对勾标记,请使用以下 CSS。

/* Remove the default checkmark from the selected option */
option::before {
 display: none;
}

虽然选择器中可以包含无限数量的元素,但浏览器会将 <button> 元素之外的所有内容归入 ::picker(select) 伪元素,该伪元素会充当锚定到按钮的弹出式窗口。此 <button> 用于切换 ::picker(select)。直接位于 select 内部的选项和其他元素将被提升到 ::picker(select) 中,您也可以自行提供封装容器,以便设置样式。此封装容器也将放置在 ::picker(select) 伪元素内。

<select>
  <button>
    <selectedoption></selectedoption>
  </button>
  // Everything else that will go into the ::picker(select) popover
</select>

新的可自定义 <select> 使用了 popover 和锚点定位中的功能。它基于以下两项底层技术构建。这意味着,选择器中的下拉选项列表会充当锚定到触发按钮(用于打开选择器)的弹出式窗口。

您可以使用锚点定位来设置此 ::picker(select) 弹出式窗口的样式(包括将其锚定到其他元素)。这种内容模型还意味着,顶层动画样式可与选项列表搭配使用,以实现进入和退出效果的动画。

增强现有的 <select> 元素

此前,Chrome 团队一直在研究 <selectlist> 元素。本文介绍的是经过重新设计的功能,它会重复使用现有的 <select> 元素。

重复使用现有 <select> 元素的一个主要好处是能够逐步增强基本 HTML 元素。与全新元素相比,重复使用 <select> 仍会在网页上呈现有意义的内容。以下示例展示了自定义选择器与使用不受支持浏览器的用户所看到的选择器之间的对比:

option 中的所有文本内容都会在 select 元素的后备版本中呈现。

基本样式

这些更改可能只是选择元素的视觉样式。例如,更新按钮样式、悬停和焦点样式,或选择选项的背景。使用 appearance: base-select 选择启用后,您可以将所需的任何 CSS 应用于所选部分。

使用默认按钮更改选择框各个部分的样式。

如需自定义箭头指示器,请在选择器中添加您自己的按钮和箭头。

<select>
  <button>
    <selectedoption></selectedoption>
    <span>
      // Arrow here
    </span>
  </button>
  // Everything else that will go into the ::picker(select) popover
</select>

然后,设置箭头的样式:

/* style the arrow */
button span {
  /* arrow styles */
  transition: rotate 0.2s;
}

/* adjust arrow styles when the picker is open */
select:open button span {
  rotate: -180deg;
}

选项中的复杂内容

更进一步,您可以在 <select> 内的 <option> 元素中添加字符串以外的内容并设置其样式。一个基本示例是在下拉菜单中的国家/地区名称旁边添加国旗图片。为此,请在选项文本旁边添加一个图片元素。

<option value="france">
  <img src="img/flag_of_france.svg" alt="" />
  <span>France</span>
</option>
带有国旗的国家/地区选择器。

更复杂的示例可能包括个人资料照片、姓名和备选信息,以帮助您决定在下拉菜单中选择哪一项。

<option value="eur">
    <img src="euro-flag.png" alt="" />
    <div class="currency">
      <div class="currency-short">EUR</div>
      <div class="currency-long">Euro</div>
    </div>
    <div class="symbol" aria-hidden="true">€</div>
</option>
货币选择器的屏幕截图。

设置所选选项的样式

您可能希望所选选项在选中状态下的显示方式与在下拉菜单中的显示方式不同。Gmail 界面就是一个例子,为了节省空间,一旦选中某个选项,标签就会被移除。为此,请挂接到 <selectedoption> 元素以设置样式。<option> 包含以下所有标记:

 <option value="reply-all">
    <img class="material-symbol"  src="material-symbol-reply.png">
    <span class="text">Reply all</span>
  </option>

现在,在 <selectedoption>' 内的 .text 上应用 display: none,以隐藏文本内容并仅显示图标:

selectedoption .text {
  display: none;
}
Gmail 样式的选择器,带有表示所选选项的图标。

互动选项

由于可以完全控制 ::picker(select) 的样式,因此您可以在上一个演示的基础上进行构建,使其在悬停和聚焦时具有互动性。在此演示中,新的 calc-size() 函数用于为选择器的宽度添加动画效果,使其在悬停时或在选择器具有 focus-visible 选项时,从显示图标变为显示选项的完整宽度。

/* base styles when picker is open but not interacted with */
::picker(select) {
  width: var(--icon-width);
  transition: width 0.5s;
}

/* animate the text in on hover & focus */
::picker(select):hover,
select:has(option:focus-visible)::picker(select) {
  /*  auto width!  */
  width: calc-size(auto, size + 0.5rem);
}
Gmail 风格的互动式选择,在悬停或聚焦时会逐步显示内容。

限制和无障碍功能说明

能力越大,责任越大。为了确保无障碍体验,此功能存在一些限制。

  • 除了 <option> 元素之外,<select> 内部尚不允许使用任何互动(可聚焦)元素,例如按钮或其他元素。目前,建议的内容模型仅允许使用 <div>、<span>、<option>、<optgroup>、<img>、<svg> 和 <hr> 元素。
  • 拆分按钮目前处于实验阶段,我们正在努力寻找一种无障碍解决方案。

未来,随着这些体验的无障碍功能不断完善,内容模型预计会变得更加灵活。

总结

我们很高兴看到此功能在工作组和标准机构中取得进展,并分享我们在积极构建原型和评估此功能形态方面的进展。如果您遇到任何不符合预期的情况,请告诉我们!

虽然此功能仍在开发中,但我们非常期待您通过这份简短的反馈表单提供反馈。

感谢您与我们一起努力,确保我们能够正确实现这一目标,并让您更轻松地在 Web 上构建无障碍、可自定义的表单控件!