弹出式窗口在网络上随处可见。您可以在菜单、切换提示和对话框中看到它们,这些图标用于账号设置、披露信息微件和商品卡片预览等功能。尽管这些组件非常常见,但在浏览器中构建它们仍然令人惊讶地繁琐。为解决此问题,我们将为浏览器推出一组用于构建弹出式窗口的新声明式 HTML API,其中第一个是 Popover API。
Popover 是基准新推出的一部分。
人们常常会将弹出式窗口与对话框混淆。不过,它们在行为方面存在一些重要区别。使用 dialog.showModal
(模态对话框)打开的 dialog
元素是一种体验,需要用户明确互动才能关闭模态窗口。popover
支持轻触关闭。模态 dialog
不会。模态对话框会使网页的其余部分处于惰性状态。popover
则不会。详细了解差异。
本文是系列文章中的一篇,介绍了电子商务公司如何使用新的 CSS 和界面功能增强其网站。在本文中,了解 Tokopedia 如何实现 Popover API 并从中受益。
Tokopedia
使用 popover 属性可在 React 中最多减少 70% 的代码行。模态窗口可以通过 HTML 原生控制,而无需在 JavaScript 中进行事件处理,也不需要使用
React.createPortal
将模态 DOM 移至document.body
的末尾。我们还可以使用@starting-style
为弹出式窗口的打开和关闭添加动画效果。- Andy Wihalim,Tokopedia 高级软件工程师。
Tokopedia 的商品详情页面 (PDP) 包含每件商品的多张商品图片。点击商品缩略图后,系统会打开一个模态窗口来显示放大的图片。这是电子商务网站中常用的一种模式。
代码
Tokopedia 使用 React 进行前端开发。在针对此模态实现弹出式窗口 API 之前,他们使用了 DOM 模态和一个按钮。该按钮更改了 React 状态以打开模态窗口。使用 popover API,他们在用于打开 popover 的元素中指定 popovertarget
属性,其值与 popover 元素的 ID 相同。
采用此基本实现后,弹出式窗口可以正常运行,但在显示和消失时没有任何动画效果。如需为弹出式窗口创建流畅的进入和退出动画,请使用 :popover-open
和 @starting-style
,并允许对离散属性进行动画处理。在以下代码示例中,该动作使用 transform: 'scale()'
属性来缩放和放大 popover。
此代码示例展示了如何为 popover API 实现进入和退出动画。
<Thumbnail popovertarget="medialightbox" />
<MediaLightbox popover id="medialightbox" />
export const cssModalWrapper = css({
background: NN0,
border: 'none',
borderRadius: '.625rem',
width: 1024,
padding: 24,
'&::backdrop': {
opacity: 0,
transitionProperty: 'opacity, display',
transition: '.25s ease-out',
transitionBehavior: 'allow-discrete',
},
transitionProperty: 'transform, opacity, display',
transition: '.25s ease-out',
transitionBehavior: 'allow-discrete',
transform: 'scale(0.8)',
opacity: 0,
'@starting-style': {
transform: 'scale(1)',
opacity: 1,
},
'&:popover-open': {
transform: 'scale(1)',
opacity: 1,
'@starting-style': {
transform: 'scale(0.8)',
opacity: 0,
},
},
});
为了适应不支持 popover API 的浏览器,Tokopedia 实现了 oddbird 的 popover-polyfill,该 polyfill 经过 gzip 压缩后只有 3.2 KB。他们对该 polyfill 感到满意,因为它运行良好且不会导致性能回归。总体而言,他们能够使用 popover API 在 React 中最多减少 70% 的代码行。
使用 Popover API 时的注意事项
Tokopedia 使用 React,该团队通过为不使用该组件的页面卸载弹出式窗口组件,然后为弹出式窗口内容进行代码拆分,实现了代码拆分。这样,他们就缩减了初始请求的大小。
不妨考虑将弹出式窗口与 CSS 锚点定位(即将在 Chrome 中推出)相结合,以相对于其他元素定位弹出式窗口。例如,这对菜单和提示很有帮助。
资源
- 推出 popover API
- 弹出式窗口和对话框的区别
- 您想报告 bug 或请求新功能吗?我们期待收到您的反馈。
阅读本系列中的其他文章,了解电子商务公司如何通过使用新的 CSS 和界面功能(例如滚动条驱动的动画、弹出式窗口、容器查询和 has()
选择器)获益。