红点必须用::after伪元素+absolute定位,禁用字符●;data-unread属性控制显隐更可靠;父容器relative+transform:translate(50%,-50%)精准锚定;移动端需适配尺寸;overflow:hidden会裁剪红点。

红点不是加个 • 就完事——它必须用 ::after 伪元素 + position: absolute,否则在不同字体、行高、缩放下必然错位。
为什么不能直接用字符 ● 当红点
字符 ● 是文本节点,受 font-size、line-height、字体度量(如 ascent/descent)影响极大。同一行内,<i></i> 和 <span></span> 包裹 ●,位置可能差 3px 以上;iOS Safari 下还容易糊边。真正可控的方式是用 content: "" 配合 background-color 和 border-radius: 50% 画圆。
-
●在rem缩放时会失真,而固定width: 8px; height: 8px始终精准 - 字符无法做
opacity过渡动画,display: none切换还会触发重排 - 多语言环境里,某些字体把 ● 渲染成椭圆或带锯齿,尤其在 Windows Chrome 上
data-unread 属性比 class 更可靠
用 [data-unread="1"] .badge { display: block; } 控制显隐,而不是靠 JS 切换 .show 类。这样避免框架更新时 class 被意外移除(比如 Vue 中 v-if="unread" 会让属性彻底消失),也方便用 CSS 实现淡入:transition: opacity 0.2s; opacity: 0; [data-unread="1"] .badge { opacity: 1; }。
- React 中写
data-unread={unread ? "1" : "0"},强制字符串化,防止属性被删 - Vue 中推荐用
:attr="{ 'data-unread': unread ? '1' : '0' }",不依赖v-bind:class的布尔逻辑 - 千万别用
:empty判断——哪怕标签里有个空格,:empty就失效
定位总偏移?只调这四个值就够了
红点贴右上角却“悬空”或“压字”,问题几乎全出在定位基准没对齐。父容器必须是 position: relative,红点本身用 top: 0; right: 0; transform: translate(50%, -50%) 锚定图标右上顶点——这是唯一能绕过基线(baseline)干扰的方案。
立即学习“前端免费学习笔记(深入)”;
- 图标若为
<i>或<svg>,确保其display是inline-block或block,别让它按 inline 默认基线对齐 - 移动端加
@media (max-width: 768px) { .badge { width: 6px; height: 6px; } },不然小屏看着像血滴 - 如果红点要显示数字(如
9+),用content: attr(data-count),但注意后端/JS 必须提前拼好字符串,attr()不支持表达式
最易被忽略的一点:红点是否“随父容器隐藏”取决于 overflow。如果消息图标在 overflow: hidden 的导航栏里,红点超出部分会被裁掉——此时要么改父容器 overflow: visible,要么把红点提到更高层级(加 z-index: 1000 并确保父级有定位上下文)。



















