::before 里加文字不显示的最常见原因是未设置 content 属性;此外 display 默认为 inline,遇 flex/grid 布局易塌陷或溢出,且需注意字体继承、XSS 风险、可访问性及动态内容限制。
最常见原因是没设置 content 属性——伪元素默认为空,不写 content 就算写了 ::before 也完全不可见。另外,display 默认是 inline,如果父元素是 flex 或 grid 且没设对齐方式,文字可能被挤出视口或塌陷。
修饰性文字(比如「·」、「→」、「【新品】」)本质是视觉补充,不该影响语义结构,所以用 ::before 合理。关键点:
content 必须是字符串、属性值或空字符串(content: ""),不能直接写纯文本\a 换行需配合 white-space: pre)
font-weight 常不继承)content: attr(data-label) 插入用户可控内容,有 XSS 风险(尤其在 SSR 场景)button::before {
content: "★ ";
font-family: "Segoe UI", sans-serif;
font-size: 12px;
font-weight: bold;
color: #ff6b35;
margin-right: 4px;
}
伪元素默认基线对齐,但修饰符号(如图标、小标签)常需要垂直居中或顶部对齐。这时候不能只靠 vertical-align,得结合 line-height 和 transform:
transform: translateY(-20%) 微调line-height 固定,伪元素也设相同值,并加 vertical-align: middle
top/bottom 定位,除非已设 position: absolute(此时脱离文档流,需手动控制尺寸)::before 在 IE8+ 和所有现代浏览器都支持,但要注意:
content 中的纯字符串(如 "→"),不会读出来;若该符号承载语义(如「必填」),应改用真实 + aria-label
content 默认不输出,如需保留,得显式写 @media print { ::before { content: "★ "; } }
::before 里塞长段落或按钮逻辑——它不是 DOM 节点,无法绑定事件、无法聚焦、无法被 JS 查询到 textContent
真正麻烦的是动态内容:想让 ::before 显示不同文字,只能靠切换 class 或 JS 改 data- 属性再用 attr(),没法直接操作伪元素内容本身。