ant-design Badge 徽标数深度指南:封顶数字、状态点、缎带与 Semantic DOM 定制
本文围绕 ant-design 的 Badge(徽标数)组件展开,基于官方文档 Badge 中文文档 的完整 API 体系,结合 Badge 主组件实现、Ribbon 缎带实现 与 样式 Token 定义 的源码细节,讲解如何在通知图标、头像、卡片等场景中使用 Badge 展示消息数、状态点与缎带标记,以及如何通过 Semantic DOM 和 Design Token 对其进行精细化定制。
何时使用
Badge 一般出现在通知图标或头像的右上角,用于显示需要处理的消息条数,通过醒目的视觉形式吸引用户去处理。它属于 ant-design「数据展示」类组件,除了数字徽标外,还提供三种形态:独立小红点(dot)、状态点(status)、以及包裹在内容角部的缎带(Badge.Ribbon)。
基础用法与核心演示
基本徽标
最典型的用法是把徽标目标(如头像)作为 children 传入,count 传入要展示的数字。官方示例 basic.tsx 展示了三种形态:普通数字、showZero 展示 0、以及用图标作为 count 内容:
import { Avatar, Badge, Space } from 'antd';
import { ClockCircleOutlined } from '@ant-design/icons';
export default () => (
<Space size="medium">
<Badge count={5}>
<Avatar shape="square" size="large" />
</Badge>
<Badge count={0} showZero>
<Avatar shape="square" size="large" />
</Badge>
<Badge count={<ClockCircleOutlined style={{ color: '#f5222d' }} />}>
<Avatar shape="square" size="large" />
</Badge>
</Space>
);
从 Badge.tsx 的源码可以看到,当 count 是一个 React 元素(isPlainObject(livingCount))时,组件会通过 cloneElement 把它克隆进徽标容器,并合并外部 style——这就是「用图标替代数字」的实现原理。此时数字徽标会带上 -custom-component 类名(见 ScrollNumber.tsx)。
封顶数字(overflowCount)
当 count 大于 overflowCount 时,展示为 ${overflowCount}+。默认封顶值为 99(见 Badge.tsx 中 overflowCount = 99 的解构默认值)。核心计算逻辑在 Badge.tsx:
const numberedDisplayCount = (
(count as number) > (overflowCount as number) ? `${overflowCount}+` : count
) as string | number | null;
官方示例 overflow.tsx 演示了 <Badge count={1000} overflowCount={999} /> 显示为 999+ 的封顶效果。
动态变化与小红点
官方 change.tsx 用 useState 驱动 count 增减,展示数字变化时的过渡动画;同时用 Switch 控制 dot 属性开关小红点。
关于动画,有两层实现值得注意:
- 出现/消失动画:
Badge用CSSMotion包裹徽标,motionName为${prefixCls}-zoom,对应 样式文件 中的antZoomBadgeIn/antZoomBadgeOut关键帧(独立使用时为antNoWrapperZoomBadgeIn/Out,不带位移)。 - 数字滚动动画:ScrollNumber.tsx 中,只有整数才会被拆分为逐位渲染——每一位由 SingleNumber.tsx 负责纵向滚动切换,从而产生「数字翻牌」效果;非整数或非数字内容则原样展示。
另外,源码用 countRef / displayCountRef / isDotRef 三个 ref 缓存隐藏前的数值与 dot 状态(见 Badge.tsx),注释说明其目的是「移除动画进行时不应改变计数显示」,避免徽标淡出过程中内容闪烁。
大小(size)
size 在设置了 count 的前提下有效,取值为 medium(默认)或 small,官方示例见 size.tsx。注意 size="default" 已被标记为废弃:Badge.tsx 在开发环境下会输出 size="default" 将被移除、请使用 size="medium" 的告警,对应样式类为 样式文件中的 -count-sm 规则(更小的 minWidth、height、fontSize 与 borderRadius)。
Badge 完整 API
以下参数表继承自官方文档 Badge API,并结合源码补充了实现层面的说明。通用属性(如 rootClassName)遵循 ant-design 通用属性约定。
| 参数 | 说明 | 类型 | 默认值 | 版本 | 全局配置 |
|---|---|---|---|---|---|
| color | 自定义小圆点的颜色 | string | - | × | |
| count | 展示的数字,大于 overflowCount 时显示为 ${overflowCount}+,为 0 时隐藏 |
ReactNode | - | × | |
| classNames | 用于自定义组件内部各语义化结构的 class,支持对象或函数 | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | 5.7.0 | |
| dot | 不展示数字,只有一个小红点 | boolean | false | × | |
| offset | 设置状态点的位置偏移 | [number, number] | - | × | |
| overflowCount | 展示封顶的数字值 | number | 99 | × | |
| showZero | 当数值为 0 时,是否展示 Badge | boolean | false | × | |
| size | 在设置了 count 的前提下有效,设置小圆点的大小 |
medium | small |
- | - | × |
| status | 设置 Badge 为状态点 | success | processing | default | error | warning |
- | × | |
| styles | 用于自定义组件内部各语义化结构的行内 style,支持对象或函数 | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | 5.7.0 | |
| text | 在设置了 status 的前提下有效,设置状态点的文本 |
ReactNode | - | × | |
| title | 设置鼠标放在状态点上时显示的文字。设置为 null 或 false 时移除原生 tooltip |
string | null | false | - | 6.5.0 | × |
各参数的源码级说明
count / showZero / 隐藏逻辑。 判断徽标是否隐藏的核心在 Badge.tsx:
const isZero =
numberedDisplayCount === '0' || numberedDisplayCount === 0 || text === '0' || text === 0;
const ignoreCount = count === null || (isZero && !showZero);
即:count 为 null,或为 0 且未开启 showZero 时,计数不渲染;dot 模式下 showAsDot = dot && !isZero,因此 count={0} dot 同样不显示小红点。
offset。 offset 数组的第一个值会被解析为水平偏移并取负(insetInlineEnd: -horizontalOffset,正值表示向外推),第二个值作为 marginTop,实现见 Badge.tsx。默认情况下徽标通过 position: absolute; top: 0; insetInlineEnd: 0; transform: translate(50%, -50%) 定位在目标右上角(见 样式文件),offset 是在此基础上的微调。
color。 源码通过 isPresetColor(color, false) 区分预设色板与自定义颜色:预设色(pink、red、cyan 等)会生成 -color-${color} 类名,其背景色由 样式文件中的 genPresetColor 统一派生;非预设的自定义颜色则以内联 style(background/color)注入(见 Badge.tsx 及 L292-L295)。
title。 默认行为是:当 count 是字符串或数字时,自动把该值作为原生 title tooltip 展示;显式传入 null 或 false 会移除原生 tooltip,实现见 Badge.tsx 的 titleNode 计算。
状态点分支。 当没有 children 且设置了 status 或 color(且 ignoreCount)时,组件走独立的「状态徽标」渲染分支:输出一个内联 span,内含状态点 -status-dot 和可选的 -status-text 文本,见 Badge.tsx 与 L240-L258。官方 status.tsx 演示了全部五种状态及带文本的形态:
import { Badge, Space } from 'antd';
export default () => (
<>
<Space>
<Badge status="success" />
<Badge status="error" />
<Badge status="default" />
<Badge status="processing" />
<Badge status="warning" />
</Space>
<Space vertical>
<Badge status="success" text="Success" />
<Badge status="error" text="Error" />
<Badge status="processing" text="Processing" />
{/* ... */}
</Space>
</>
);
其中 processing 状态点的呼吸动画由 样式文件中的 antStatusProcessing 关键帧 驱动(scale(0.8) → scale(2.4) 并淡出)。此外,当 text === 0 时状态文本的显示同样受 showZero 控制(见 Badge.tsx)。
Badge.Ribbon 缎带
Badge.Ribbon 用于在卡片等容器右上角包裹一条斜切缎带,官方示例见 ribbon.tsx:
import { Badge, Card, Space } from 'antd';
export default () => (
<Space vertical size="medium" style={{ width: '100%' }}>
<Badge.Ribbon text="Hippies" color="pink">
<Card title="Pushes open the window" size="small">
and raises the spyglass.
</Card>
</Badge.Ribbon>
<Badge.Ribbon text="Hippies" color="cyan">
<Card title="Pushes open the window" size="small">
and raises the spyglass.
</Card>
</Badge.Ribbon>
</Space>
);
| 参数 | 说明 | 类型 | 默认值 | 版本 | 全局配置 |
|---|---|---|---|---|---|
| classNames | 用于自定义组件内部各语义化结构的 class,支持对象或函数 | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | 6.0.0 | |
| color | 自定义缎带的颜色 | string | - | × | |
| placement | 缎带的位置,start 和 end 随文字方向(RTL 或 LTR)变动 |
start | end |
end |
× | |
| styles | 用于自定义组件内部各语义化结构的行内 style,支持对象或函数 | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | 6.0.0 | |
| text | 缎带中填入的内容 | ReactNode | - | × |
从 Ribbon.tsx 的源码看,渲染结构为:外层 div.antd-ribbon-wrapper(相对定位的包裹层)→ 子内容 → div.antd-ribbon(缎带本体,携带 antd-ribbon-placement-{placement} 与 antd-ribbon-color-{color} 类名)→ 内部 span.antd-ribbon-content(文本)与 div.antd-ribbon-corner(右下角的三角补角)。缎带的斜切造型由 Token 派生的 badgeRibbonCornerTransform / badgeRibbonCornerFilter 控制(见 Token 定义)。颜色机制与 Badge 一致:预设色走 genPresetColor 类名,自定义色以内联 background 注入,并同步给 corner 元素的 color(见 Ribbon.tsx)。RTL 环境下会自动追加 antd-ribbon-rtl 类适配方向。
Semantic DOM:语义化结构与 classNames / styles
ant-design 5.7.0 起,Badge 支持通过 classNames / styles 精确定制内部各语义化结构,官方文档通过 语义结构示例 展示了可定制的部分。从源码中的 BadgeSemanticType 定义(Badge.tsx)可确认 Badge 暴露两个语义节点:
| 语义节点 | 含义 |
|---|---|
| root | 徽标根元素(span.antd-badge) |
| indicator | 右上角的徽标本体(数字、小红点或自定义内容) |
Ribbon 的 RibbonSemanticType(Ribbon.tsx)则暴露三个语义节点:root(wrapper 包裹层)、content(缎带文本)、indicator(缎带本体)。
两者均支持「对象」或「函数」两种写法,函数形式可拿到 { props } 依据当前属性做条件定制。合并逻辑由 useMergeSemantic 工具完成,优先级为:ConfigProvider 全局配置(contextClassNames/contextStyles,key 为 badge / ribbon)< 组件自身属性,见 Badge.tsx。使用 ConfigProvider 的 theme.components.Badge 或 badge 组件级配置即可全局下发这些语义样式。
一个典型的语义定制写法:
<Badge
count={5}
classNames={{ indicator: 'my-indicator' }}
styles={{ root: { marginLeft: 8 } }}
>
<Avatar shape="square" size="large" />
</Badge>
主题变量(Design Token)
官方文档页尾通过 ComponentTokenTable 自动生成 Badge 的 Token 表格;这些 Token 的源码定义位于 style/index.ts。其中关键的组件级 Token 包括:
| Token | 说明 |
|---|---|
| indicatorZIndex | 徽标 z-index |
| indicatorHeight | 徽标高度(默认尺寸) |
| indicatorHeightSM | 小号徽标高度 |
| dotSize | 点状徽标尺寸 |
| textFontSize / textFontSizeSM | 徽标文本尺寸(默认 / 小号) |
| textFontWeight | 徽标文本粗细 |
| statusSize | 状态徽标尺寸 |
| paddingInline | 多字符徽标水平内边距 |
此外还有派生 Token(BadgeToken):badgeColor(徽标主色)、badgeColorHover(悬停色)、badgeTextColor(文本色)、badgeShadowSize / badgeShadowColor(外圈白色描边阴影,即 -count 与 -dot 上的 box-shadow: 0 0 0 {size} {color})、badgeProcessingDuration(processing 动画时长)、badgeRibbonOffset / badgeRibbonCornerTransform / badgeRibbonCornerFilter(缎带偏移、角部变换与滤镜)。这些 Token 均可通过 ConfigProvider 的 theme.token / theme.components.Badge 覆盖,从而全局调整徽标配色与几何尺寸。
实现细节速览:源码结构与类名机制
综合 Badge.tsx 与 样式文件,Badge 的关键行为可以归纳为:
- wrapper 与非 wrapper:无
children时根节点附加antd-badge-not-a-wrapper类,动画关键帧与定位方式随之切换(不位移的 zoom 动画)。 - 多词计数:
count字符串长度大于 1 时附加antd-badge-multiple-words类(横向内边距由paddingInline控制),数字包裹在<bdi>中以unicodeBidi: plaintext保证双向文本排布正确(见 样式文件 与 ScrollNumber.tsx)。 - borderColor 兼容:老版本允许用
style={{ borderColor }}给徽标加描边,ScrollNumber.tsx 将其模拟为box-shadow: 0 0 0 1px {borderColor} inset,保持旧用法兼容。 - RTL 支持:根节点与缎带在
direction === 'rtl'时分别追加antd-badge-rtl/antd-ribbon-rtl类,偏移量使用逻辑属性insetInlineEnd实现方向自适应。 - 主题与 CSS-in-JS:组件样式由 useStyle 以 cssinjs 方式生成,支持 cssVar 模式(
cssVarCls),动画关键帧(antZoomBadgeIn/Out、antStatusProcessing等)随组件样式一起注入。
小结
Badge 组件以 count 为核心,围绕封顶展示(overflowCount)、零值控制(showZero)、红点(dot)、状态点(status + text)、自定义颜色(color)、位置微调(offset)、尺寸(size)与原生 tooltip(title)提供完整的通知类视觉方案;Badge.Ribbon 则补充了容器角部缎带形态。工程层面,它通过 Semantic DOM(classNames/styles)暴露 root/indicator(Ribbon 另有 content)语义节点,并通过 style/index.ts 定义的组件 Token 支持全局主题化定制。如需查阅完整演示,可参考官方文档页列出的 demo 目录 下 17 个示例,包括动态变化、可点击、语义结构样式与 Ribbon Debug 等场景。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00