HTML Popover API 实战:手搓通知气泡和下拉菜单

2026-08-28 0 590

浏览器终于开窍了,HTML 现在能原生创建气泡、菜单、通知,关键是不用写一堆 JS 控制显示/隐藏,也不用非要套一个 dialog。今天拿 Popover API 做个通知中心和一个下拉菜单,保准你用过就不想搞老一套。

Popover 是什么?

简单说,popover 属性让一个元素藏起来,点击某个按钮就能切换显示。还能点外部自动关闭、按 Esc 关闭,那些历史上自己写的点击外部隐藏逻辑一下子全不要了。

最基础用法就是一个按钮加一个带 popover 的元素,然后用 popovertarget 关联上。

<button type="button" popovertarget="my-popover" popovertargetaction="toggle">点我看看</button>
<div id="my-popover" popover>
  这是原生气泡
</div>
    

注意:popovertargetaction 还支持 showhide,一般 toggle 就够用了。

先用一个通知例子试试水

通知一般停几秒就自己没了,其实 Popover 不管自动隐藏,但咱们可以自己加个 setTimeout 控制。

先放 HTML,模拟一个通知气泡:

<div id="notice" popover role="status">已保存修改</div>
<button type="button" popovertarget="notice" popovertargetaction="show">保存</button>
    

注意到 role="status" 吗?给读屏软件用的,屏幕阅读器会播报。原生弹窗终于能自然配合无障碍了。

自动关闭得用 JS 调 hidePopover()。其实也很简单,咱们加个小计时器:

const saveBtn = document.querySelector('[popovertarget="notice"]');
const notice = document.getElementById('notice');

saveBtn.addEventListener('click', () => {
  notice.showPopover();
  setTimeout(() => {
    if (notice.matches(':popover-open')) {
      notice.hidePopover();
    }
  }, 2000);
});
    

看起来还是有点小 JS。那有没有更“原生”的自动关闭?有,popoverinterest 或者 light-dismiss 都不自动关闭。所以老实写个 setTimeout 就行。

真·下拉菜单:不用 JS 控制开关

做导航菜单,最烦的就是点击别处能不能收起。以前要监听全局 click,还要判断是否在元素内。现在直接在按钮上用 popovertarget 就完事了。

先来个实际的菜单布局:

<div class="user-menu-wrap">
  <button class="avatar-btn" popovertarget="user-menu" popovertargetaction="toggle">
    账号
  </button>
  <div id="user-menu" popover>
    <div class="menu-item">个人资料</div>
    <div class="menu-item">订单记录</div>
    <div class="menu-item">退出登录</div>
  </div>
</div>
    

啥 JS 都不用写,点按钮就切换,点菜单外部自动关,按 Esc 也能关。你要是愿意,还能给每个菜单项加上 data-action,再统一挂事件。

然后这里有个坑:如果菜单内部再有弹层(比如子菜单),得给子菜单加 popover="manual" 防止父菜单被点外面自动关掉。对,popover 有两个值:

  • popover="auto"(默认):点外部 / Esc 自动关,且同时只会显示一个 auto 弹层。
  • popover="manual":手动开关,点外部不关,Esc 也不关。

导航菜单一般用 auto 就合适。但如果你做一个悬浮提示,想让它停留久一点,反而用 manual 更稳。

高级组合:Popover 和 CSS 锚点定位

今天的热门话题还有一个:锚点定位(Anchor Positioning)。简单来说,让气泡出现的位置尽量贴紧触发按钮,而不是默认居中或固定位置。这个 API 还在实验阶段,但 Chrome 已经能跑。

它和 Popover 配合,菜单就能做到绝对定位到按钮旁边,即使页面滚动也不会跑偏,而且无需 JS 计算位置。

举个例子,给按钮添加 anchor-name,然后让气泡用 position-anchor 绑定:

<style>
  /* 注意:这属于实验性 CSS,不在本文样式范畴,仅演示结构 */
</style>
    

咱们不写样式,只说结构。但你不要真的完全不用 CSS,锚点定位必须要 CSS 设 anchor-name。其实 HTML 那边也有个 anchor 属性,但还没普及。直接看个代码意思:

<button class="anchor" popovertarget="tooltip">悬停我</button>
<div id="tooltip" popover="manual">我是提示</div>
    

CS 里大概这么配:

.anchor { anchor-name: --btn; }
#tooltip { position: anchor(--btn); top: anchor(--btn bottom); }
    

不过这个 CSS 牵扯到新知识,不建议今天就用,但可以当成以后的热点。

当心:Safari 和 Firefox 的兼容性

Chrome 117 早支持了,Edge 也都行,问题最大的是 Safari 直到 17.4 才支持,Firefox 目前仍然默认不支持 Popover API(截至 2025 年中,但 Flag 已经能开)。所以如果你要发布到面向国内用户为主的站点,那基本能用了,毕竟大家在 Chromium 核心上。

如果实在要兼容 Firefox,可以用 dialog 元素做降级的弹窗,或者用老掉牙的 div+class 切换,但那个咱们不写。

完整的可运行案例:消息通知中心

直接放一个能跑的例子。不用 CSS,只看到结构。

<!DOCTYPE html>
<html lang="zh">
<body>
  <h3>消息通知</h3>
  <button type="button" popovertarget="notification-pop" popovertargetaction="toggle">
    查看未读消息 (3)
  </button>
  <div id="notification-pop" popover>
    <h4>你有三条新消息</h4>
    <ul>
      <li>有人回复了你的评论</li>
      <li>你的账单已生成</li>
      <li>新版本上线,点击更新</li>
    </ul>
    <button popovertarget="notification-pop" popovertargetaction="hide">确实,已读</button>
  </div>
</body>
</html>
    

等等,按钮“确实,已读”还是用 Popover 自己隐藏。你可以在这里做点 JS,比如点击后通过 fetch 把消息标记为已读,但这里就不画蛇添足了。

跑起来你会看到:点“查看未读消息”弹出来,再点一下按钮弹层关闭,按 Esc 也关闭,点击外面一层也会自动关。这些行为统统是浏览器默认的,没写一行 JS。

一个容易踩的坑

如果把 popover 元素放在隐藏的容器里,比如 display:none 的父级,它依然能通过 showPopover() 显示吗?答案是:可以,但是位置会有问题,因为气泡默认默认定位在视口中间,不会受父级影响。如果你想让气泡出现在按钮附近,依然需要 CSS 定位。所以通常把气泡直接放到 body 下面。

另外,popovertarget 指向的 id 必须是唯一的,如果页面上有两个相同 id,只有第一个会有效。这不用多说了吧。

还是得聊两句性能

原生 API 比用 JS 改 display 的性能高那么一丢丢,但主要优势是代码量少。尤其遇到需要多个可展开菜单的情况,不用维护一堆布尔变量。比如做一个 FAQ 列表,每个答案都是带 popover="manual" 的元素,点击问题切换。JS 就只需要几行 togglePopover(),比老方案清爽。

总之,Popover API 是 HTML 里少有的“功能补完型”特性,值得在项目里用起来。别怕它不是“新 CSS 魔法”,这东西才是真正的生产力。

总结一下

这次用 Popover 做了通知和菜单,核心点就三个:

  • popover 属性让元素变成弹层;
  • popovertarget 关联按钮和弹层;
  • popovertargetaction 指定动作是开、关还是切换。

再记一个 popover="manual",用来控制是否允许外部点击关闭。后面等锚点定位全面支持,就能做到真正“贴着按钮”的菜单,到时候再写一篇。

浏览器厂商最近都在卷这种“原生组件”,咱们做前端的终于能少写一些封装的 dropdowm 函数了。不过玩笑归玩笑,你自己的项目还是得先重点看浏览器兼容,最好降级方案也留着。

完。

HTML Popover API 实战:手搓通知气泡和下拉菜单
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

版权声明:
本站资源有的来自互联网收集整理,本站纯免费分享提供学习使用,如果侵犯了您的合法权益,请发送邮件1506151422@qq.com联系,将会及时下架删除。
本站资源仅供研究、学习交流之用,免费开源项目不代表完全可商用,若商业用途请先咨询开发企业能否商用,否则产生的一切后果将由下载用户自行承担。
原创板块未经允许不得转载,否则将追究法律责任。

淘吗网 html HTML Popover API 实战:手搓通知气泡和下拉菜单 https://www.taomawang.com/web/html/2656.html

常见问题

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务