Popover 案例研究

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

弹出式窗口随处可见。您可以在菜单、切换提示和对话框中看到这些选项,这些对话框用于帐号设置、披露声明 widget 和产品卡片预览等功能。尽管这些组件非常普遍,但在浏览器中构建它们仍然非常麻烦。为了解决此问题,我们将向浏览器推出一组新的声明式 HTML API,用于构建弹出式窗口,其中第一个是 Popover API

弹出式窗口是新推出的基准 API 的一部分。

浏览器支持

  • 114
  • 114
  • 125
  • 17

来源

弹出式窗口通常与对话框相混淆。不过,它们的行为之间存在一些关键差异。使用 dialog.showModal(模态对话框)打开的 dialog 元素是一种需要用户明确互动才能关闭模态的体验。popover 支持轻关闭。模态 dialog 则不会。模态对话框会使页面的其余部分闲置。popover 则不可以。详细了解差异

本文是系列文章的一部分,该系列讨论了电子商务公司如何使用新的 CSS 和界面功能增强其网站。本文介绍了 Tokopedia 如何实现 Popover API 并从中受益。

Tokopedia

使用弹出式窗口属性最多可减少 React 中的 70% 代码行。模态窗口可由 HTML 原生控制,而无需在 JavaScript 中处理事件并使用 React.createPortal 将模态 DOM 移至 document.body 的末尾。我们还可以使用 @starting-style 为弹出式窗口的打开和关闭添加动画效果。- Andy Wihalim,Tokopedia 高级软件工程师

Tokopedia 的商品详情页面 (PDP) 中包含了每件商品的多张商品图片。点击商品缩略图时,系统会打开一个模态窗口,以显示放大的图片。这是电子商务网站常用的模式。

代码

Tokopedia 使用 React 进行前端开发。在为此模态实现弹出式窗口 API 之前,他们使用了一个 DOM 模态和一个按钮。该按钮更改了 React 状态以打开模态窗口。借助 Popover API,他们可在元素中指定 popovertarget 属性,以通过与弹出式窗口元素的 ID 相同的值打开弹出式窗口。

使用此基本实现时,弹出式窗口可以正常工作,但会在无任何动画的情况下出现和消失。如需为弹出式窗口创建流畅的进入和退出动画,请使用 :popover-open@starting-style 并允许显示离散属性的动画。在以下代码示例中,弹出式窗口使用 transform: 'scale()' 属性进行了缩放。

代码示例展示了如何为 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',

  '@starting-style': {
    transform: 'scale(1)',
    opacity: 1,
  },
  transform: 'scale(0.8)',
  opacity: 0,

  '&:popover-open': {
    '@starting-style': {
      transform: 'scale(0.8)',
      opacity: 0,
    },
    transform: 'scale(1)',
    opacity: 1,
  },
});

为了迎合不支持 Popover API 的浏览器,Tokopedia 通过 oddbird 实现了 popover-polyfill(采用 gzip 压缩时,只有 3.2 KB)。他们对 polyfill 很满意,因为它运行良好且未导致性能下降。总体而言,他们在 React 中使用 Popover API 减少了高达 70% 的代码行数。

使用 Popover API 时的注意事项

Tokopedia 使用 React,该团队通过以下方式实现了代码拆分:为不使用弹出式窗口组件的页面卸载该组件,然后对弹出式窗口内容执行代码拆分。通过这种方式,他们减少了初始请求的大小。

考虑将弹出式窗口与 CSS 锚点定位结合使用(即将在 Chrome 中推出),以便相对于其他元素确定弹出式窗口的位置。例如,这对于菜单和提示很有帮助。

资源

浏览本系列中的其他文章,探讨电子商务公司如何利用新的 CSS 和界面功能(如滚动驱动的动画、弹出式窗口、容器查询和 has() 选择器)获益。