徽章应统一用而非,数字角标需aria-live支持动态更新,定位推荐transform: translate(50%, -50%),颜色等样式须通过语义类名和css变量实现主题适配。

有区别,而且区别直接影响语义、可访问性和维护成本。数字角标是徽章的一种子类型,但不是所有徽章都该用角标结构;反过来,把“VIP”“已认证”这类状态标识写成 <sup></sup> 或硬套 position: absolute 数字角标样式,反而会破坏语义和屏幕阅读器体验。
徽章用 <span></span>,别用 <sup></sup> 或 <sub></sub>
HTML 的 <sup></sup> 和 <sub></sub> 是语义化上标/下标标签,专用于数学公式、化学式(如 H2O)、脚注编号等场景。把它当视觉角标用,会导致:
- 屏幕阅读器读作“上标 VIP”,而非“VIP 徽章”
- CSS 重置
vertical-align后仍可能受字体 baseline 影响,对齐不稳 - 无法添加
aria-label或role="status"等语义属性(<sup></sup>不支持role)
正确做法是统一用 <span class="badge">VIP</span>,靠 CSS 控制位置和外观。语义清晰、样式可控、无障碍友好。
数字角标必须带 aria-live 才算可用
未读消息数、购物车数量这类动态数字角标,不只是“看起来在右上角”,更要让辅助技术感知变化:
- 静态数字(如固定显示“3”)加
aria-label="3 条未读消息"即可 - 动态更新时,必须包裹在
<span aria-live="polite" aria-atomic="true">3</span>中,否则屏幕阅读器不会播报更新 - 避免用伪元素
::after渲染数字——它不在 DOM 中,aria-live完全无效 - 别依赖 JS 直接改
textContent就完事,要确保父容器的aria-live区域能捕获到变更
徽章位置不能只靠 position: absolute 硬塞
把徽章塞进头像右上角,常见错误是给头像父容器加 position: relative,再给徽章加 position: absolute; top: 0; right: 0;。问题在于:
- 小屏幕下徽章可能被裁切或遮挡文字
- 不同字体渲染下,
top: 0实际偏移量不一致(尤其中文字体 baseline 差异大) - 父容器若设了
overflow: hidden,徽章直接消失
更稳妥的做法:
- 用
transform: translate(50%, -50%)配合top: -4px; right: -4px;,让尖角精准锚定 - 徽章本身设
flex-shrink: 0,防止响应式压缩变形 - 若徽章需随文本流自然换行(如昵称旁多个徽章),改用
display: inline-flex+gap,放弃绝对定位
徽章颜色和文字不能只靠内联 style 或 class 名硬编码
写 class="red-badge" 或 style="background:red" 看似快,但后期改主题时会失控:
- 换深色模式时,红色背景可能对比度不足(WCAG 要求至少 4.5:1)
- “VIP”“企业版”“试用期”等不同状态,应通过语义类名(如
badge-tier-vip)绑定 CSS 变量,而非颜色值 - 文字颜色别写死
color: white,而用color: var(--badge-fg, white),方便主题切换时统一控制 - 圆角、内边距、字号建议用 rem/em,比如
padding: 0.125rem 0.375rem,随根字号缩放
真正容易被忽略的是:徽章不是独立组件,它永远依附于某个上下文(用户头像、菜单项、卡片标题)。脱离这个上下文去定义样式,90% 的兼容性问题就源于此。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











