徽章是语义完整的独立状态标记(如“vip”),角标是依附于其他元素的数值提示(如“3”),二者在结构、定位、无障碍处理(aria-label vs aria-live)及实现方式上存在本质区别。

有区别,而且区别直接影响实现方式和可访问性。徽章是语义完整的状态标记(如“VIP”“已读”),角标是依附于其他元素的数值提示(如“3”“99+”),二者结构、用途、无障碍处理都不同。
徽章用 <span></span>,角标必须包裹在相对定位父容器里
徽章本身是独立语义单元,<span class="badge">SVIP</span> 就够了;角标则必须依赖上下文,比如头像右上角的未读数,父容器得先加 position: relative,角标再用 position: absolute 定位。否则在 flex 或 grid 布局里容易错位、被裁剪。
常见错误包括:
- 直接给角标设
position: absolute但父容器没设position: relative,结果相对于 body 定位,飘到页面角落 - 用
float模拟角标位置,导致父容器高度塌陷、响应式下换行错乱 - 把角标塞进图标
<svg></svg>的<text></text>里,导致无法复制、高对比度模式下不可见
aria-label 和 aria-live 不能混用
徽章内容本身有意义(如“企业认证”),应直接用 aria-label="企业认证";角标是动态数字(如“5条新消息”),必须配合 aria-live="polite" 让屏幕阅读器感知变化,且文本需完整表达语义,不能只写 "5"。
实操要点:
- 角标元素必须是
<span></span>或<div>,不能是伪元素 <code>::after—— 后者无法被辅助技术读取 - 数字更新时,用
element.textContent = "99+"触发aria-live,别用innerHTML插入 HTML 标签,否则可能破坏语义 - 如果角标值为 0,建议隐藏整个元素(
display: none),而不是留空或写 “0” —— 用户不需要被告知“零条新消息” - 角标字体大小建议设为
font-size: 0.75em,避免在小图标旁显得过大;徽章可用0.8em保持可读性 - 圆角统一用
border-radius: 12px,别用999px—— 高 DPI 屏幕下会渲染成椭圆 - 背景色必须满足 WCAG AA 对比度(至少 4.5:1),比如白字配
#d32f2f可行,但配#ffcc00就不行
颜色和尺寸要用 CSS 变量,别硬编码
徽章和角标常随状态变色(如“警告”红、“成功”绿、“VIP”金),用 --badge-color 这类自定义属性统一控制,比写一堆 .badge-warning { background: #d32f2f; } 更易维护。
注意几个关键细节:
最易被忽略的是:角标数字必须是纯文本节点,不能藏在 SVG <text></text> 里,也不能靠 JS 拼接进 innerHTML。它得能被复制、翻译、被浏览器的“查找”功能命中——这决定了它是不是真正可用的角标,而不仅仅是个像素点。











