前言
谷歌正在努力解决开发者长期以来对于自定义表单控件元素 <select> 的需求。该功能已进入 WHATWG 的第二阶段,并在 Chrome Canary 130 版本中提供了原型。今日前端早读课文章由 @排骨翻译分享。
译文从这开始~~
多年来,像 <select>
这样的表单控件的样式问题一直被开发者视为主要的困扰点,我们一直在寻找解决方案。虽然这项工作复杂且耗时较长,但我们已经非常接近实现这一功能。可定制的 <select>
元素已正式进入 WHATWG 的 Stage 2 阶段,并受到了跨浏览器的广泛关注,Chrome Canary 130 中还提供了一个可供测试的原型。
请确保您的 Chrome Canary 版本已更新至 130,并且启用了实验性 Web 平台功能标志。您可以通过在地址栏中输入 chrome://flags,然后开启#experimental-web-platform-features
来启用此标志。然后,您应该能够查看本文中的 Codepen 示例。或者,您可以查看这个 Codepen 集合,以便在同一位置查看所有示例。
让我们深入了解一下基于现有 HTML select 标签的可自定义选择 API 的功能。。
加入新的 <select>
要启用新行为,请在页面上的选择按钮和选择器上使用 CSS appearance 属性。要启用,请在 <select>
元素和 ::picker(select)
上设置 appearance: base-select
。
::picker(select)
是一个新的用户代理提供的伪元素,仅适用于已通过 appearance: base-select
选择新行为的 <select>
元素。这个选择器伪元素是触发基础选择按钮的弹出式面板。您可以通过以下代码同时进行选择:
select,
::picker(select) {
appearance: base-select;
}
您可以选择仅启用页面内的按钮,但你不能只启用选择器弹出框而不启用页面内的按钮。只有在应用了 appearance: base-select
之后才会创建 ::picker(select)
。
现在你可以自定义选择元素了。新的可自定义选择元素具有一些跨浏览器和操作系统的默认样式。以下是在 macOS 上的 Chrome 中默认自定义选择元素的外观:
右侧可自定义选择框的默认用户代理样式。此内容可能会有所更改
示例:https://codepen.io/web-dot-dev/pen/YzoBJRZ
注意:select (
<select multiple>
和<select size=n>
)的 multiple 和 size 属性在 appearance: base-select 中还不支持。
分解零件
选定器的组成部分示意图。
一旦进入新的可定制选择模式,您现在可以访问的新元素包括:
selectedoption :反映当前选中选项的内部 HTML。
option::before
:包含一个勾选标记,以表示当前选中的选项作为默认可访问性功能(这可能会改变)。::picker(select)
:包含所有内容的弹出窗口,包含自定义选择中所有位于button
之外的内容。
你可以对选择框的任何部分进行样式设置。例如,您可以在 <option>
元素中添加任意非交互式内容,样式化打开选择框下拉列表的在页面上的按钮,以及对选项的下拉列表( ::picker(select)
)进行样式设置。
您还可以为 button 、自定义箭头指示器以及任何元素内部和周围的任意内容设置样式。除了添加内容,您还可以隐藏这些新元素和默认样式。例如,如果您不想在 option 的 ::before
伪元素中包含指示器勾选标记,可以使用以下 CSS。
/* Remove the default checkmark from the selected option */
option::before {
display: none;
}
注意:我们非常乐意听取您对如何访问和格式化选择框中的勾选部分的意见。
虽然可以在选择器中包含任意数量的元素,但浏览器会将 <button>
元素之外的任何内容放入 ::picker(select)
伪元素中,该伪元素的行为类似于锚定在按钮上的弹出窗口。这个 <button>
可以切换 ::picker(select)
。位于选择器内部的选项和其他元素将被提升到 ::picker(select)
中,或者您可以为您的样式目的提供自己的包装器。这个包装器也将放置在 ::picker(select)
伪元素内部。
<select>
<button>
<selectedoption></selectedoption>
</button>
// Everything else that will go into the ::picker(select) popover
</select>
新的自定义下拉框使用了来自弹出框和锚定定位的功能。它是基于这两种底层技术构建的。这意味着在一个选择框中的下拉选项列表将作为锚定到触发按钮的弹出框出现,该触发按钮打开了选择框。
您可以使用锚定位来为这个 ::picker(select)
弹出框进行样式设置(包括使其锚定到其他元素)。这种内容模型还意味着顶层动画样式与选项列表一起使用,以实现进入和退出效果的动画。
增强现有的 <select>
元素
以前,Chrome 团队一直在研究如何使用 <selectlist>
元素。本文所描述的是将该功能重新设计为使用现有的 <select>
元素。
重用现有 <select>
元素的关键优势之一是可以逐步增强基本 HTML 元素。与全新的元素相比,重用 <select>
仍然可以在您的页面上渲染有意义的内容。下面的例子展示了自定义的下拉列表框与非支持浏览器用户看到的内容之间的对比:
在 option
标记内所有的文本内容都将在选择元素的默认版本中呈现。
基本样式
更改可能只是对选择元素的视觉样式进行调整。例如,可以更新按钮样式、悬停和聚焦样式,或选择选项的背景色。在使用 appearance: base-select
进行选定后,可以将任何想要的 CSS 应用于选择元素的各个部分。
更改选择器各个部分的样式,包括默认按钮。
示例:https://codepen.io/web-dot-dev/pen/zYVberJ
要自定义箭头指示器,请在选择器内部添加自己的按钮和箭头。
<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;
}
示例:https://codepen.io/web-dot-dev/pen/NWZJodg
选项内的复杂内容
使用超越 <option>
元素内部 <select>
标签中字符串的添加和样式功能,让设计更加灵活。一个简单的例子是在下拉菜单中的国家名称旁边添加旗帜图片。要实现这一点,请在选项文本旁边添加一个图片元素。
<option value="france">
<img src="img/flag_of_france.svg" alt="" />
<span>France</span>
</option>
带有国旗的国家选择器。
示例:https://codepen.io/web-dot-dev/pen/ZEdwqqN
一个更为复杂的例子可能包括个人资料图片、姓名以及其他替代信息,以帮助你做出选择,决定在下拉菜单中选择哪个项目。
<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>
货币选择器的截图
示例:https://codepen.io/web-dot-dev/pen/LYKqgXZ
选择并设置选项
你可能希望选中的选项在选中状态下的显示方式与在下拉菜单中的显示方式不同。例如,Gmail UI 中,为了节省空间,一旦选项被选中,就会移除标签。通过为样式绑定到 <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 类似的选择方式,并使用一个图标来代表所选选项。
示例:https://codepen.io/web-dot-dev/pen/rNEPqqX
交互式选项
在完全控制 ::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);
}
示例:https://codepen.io/web-dot-dev/pen/Rwzveqg
限制和可访问性说明
能力越大,责任越大。为了保持该功能的易用性,我们对其进行了一些限制。
除了 <option>
元素外,目前还不允许在 <select>
内包含任何交互式(可聚焦)元素,例如按钮或其他元素。目前,建议的内容模型只允许包含 <div>
、 <span>
、 <option>
、 <optgroup>
、 <img>
、 <svg>
和 <hr>
元素。
分按钮目前正处于实验阶段,因为我们正在寻找一个可访问的解决方案。
在未来,预计内容模型会变得更加灵活,随着这些体验的可访问性故事得到完善。
关于本文
译者:@排骨
作者:@Una Kravets
原文:https://developer.chrome.com/blog/rfc-customizable-select
这期前端早读课
对你有帮助,帮” 赞 “一下,
期待下一期,帮” 在看” 一下 。