通知徽章按钮(铃铛角标弹跳/99+ 计数源码)
通知徽章按钮:铃铛图标 + 红色角标计数,点击 +1 带弹跳动画、铃铛摇动反馈,超 99 自动显示 99+,原生 JS 实现零依赖。
效果演示(真实可交互)
徽章超过 99 显示 99+;点击铃铛也可 +1
完整代码
HTML 结构:
<button id="nb-bell" class="nb-bell" aria-label="通知">
<!-- 铃铛 SVG(stroke 描边风格) -->
<svg viewBox="0 0 24 24" width="22" height="22" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"></path>
<path d="M13.7 21a2 2 0 0 1-3.4 0"></path>
</svg>
<span id="nb-badge" class="nb-badge" hidden>0</span>
</button>
CSS 核心代码:
/* 角标:绝对定位到右上角 */
.nb-badge {
position: absolute; top: -4px; right: -4px;
min-width: 22px; height: 22px; padding: 0 5px; border-radius: 11px;
background: linear-gradient(120deg, #ff6b6b, #ff4d6d); color: #fff;
font-size: 12px; font-weight: 700; display: grid; place-items: center;
}
/* 弹跳出现 */
.nb-badge.nb-pop { animation: nb-pop .35s cubic-bezier(.34,1.56,.64,1); }
@keyframes nb-pop {
0% { transform: scale(0); }
70% { transform: scale(1.35); }
100% { transform: scale(1); }
}
/* 铃铛摇动 */
.nb-bell.nb-ring { animation: nb-shake .5s ease; }
JS 逻辑:
function bump() {
count++;
badge.hidden = false;
badge.textContent = count > 99 ? '99+' : count;
badge.classList.remove('nb-pop');
void badge.offsetWidth; // 重放弹跳动画
badge.classList.add('nb-pop');
}
参数说明
| 参数 | 取值 | 说明 |
|---|---|---|
| 角标定位 | top/right: -4px | 徽章悬在按钮右上角外侧 |
| 弹跳动画 | .35s cubic-bezier(.34,1.56,.64,1) | 回弹曲线让出现更有力 |
| 摇动动画 | nb-shake .5s | ±14° 摇动幅度,可调 |
| 上限显示 | count > 99 ? '99+' | 防止三位数撑爆角标 |
min-width + padding | 22px / 0 5px | 单位数圆形、双位数胶囊自适应 |
兼容性与性能
- 全部原生 CSS + JS,SVG 内联零请求,兼容所有现代浏览器
- 动画仅 transform 旋转/缩放,GPU 合成无压力;角标频繁更新时重绘开销极小
- 注意
aria-label与徽章文本的配合:真实项目中建议在按钮内隐藏读屏文本「有 N 条未读通知」,提升无障碍体验 - 疯狂模式用 setInterval 模拟推送场景,实际接入时替换为 WebSocket 或轮询回调即可
常见问题
Q: 徽章数字超过 999 怎么显示? 常规做法是显示 99+,再往上可显示 999+;保留原始 count 值用于 aria-label 播报,展示层单独截断。
Q: 弹跳动画为什么第一次点击不触发? 首次点击时角标从 hidden 变为显示,void offsetWidth 在元素隐藏时取不到尺寸,动画类名添加时机需在 hidden = false 之后再强制 reflow(本组件已处理),或直接用 transition 替代。
Q: 徽章能改成红点模式吗? 可以,把内容清空、宽高固定为 10px 圆点即可,常见于「无数字提醒」场景,点击后隐藏红点。
Q: 如何实现角标淡入而不是弹跳? 把 nb-pop 换成 opacity 过渡:.nb-badge { transition: opacity .25s; opacity: 0 },有值时 opacity: 1 即可。
许可与来源
- 许可证:自研原创 —— 粤喵自研原创,可免费用于个人与商业项目,无需署名。查看来源公示与许可清单
- 来源:粤喵团队原创自研(从效果思路到代码实现均为独立完成,未直接复制第三方代码)
- 首次发布:2026-09-01 · 最近更新:2026-09-01
- 修改日志:2026-09-01 首次发布;2026-09-13 补充许可证与来源标注、复制按钮说明与法务页入口
- 纠错:联系页面 / min@cactus.asia,2 个工作日内核实处理
常见问题
这个组件可以商用吗?
可以。本组件为粤喵自研原创,可免费用于个人和商业项目,无需署名。
浏览器兼容性如何?
支持所有现代浏览器(Chrome / Firefox / Safari / Edge 最新版本)。旧版 IE 不支持 CSS 动画相关特性。
怎么修改动画参数?
直接调整 CSS 中的 animation-duration(时长)、animation-timing-function(缓动曲线)等属性即可,代码中有注释说明。