:first-child不生效是因为目标元素非父容器首个子元素;应改用:nth-of-type(1)或:nth-child(1 of li);图标对齐需统一line-height并用transform微调;动态内容需配合class控制。

为什么 :first-child 有时不生效
直接写 li:first-child::before 却没看到图标?大概率是因为目标 li 前面还有别的兄弟元素(比如注释、空格文本节点,或意外插入的 div)。:first-child 要求元素必须是其父容器的「第一个子元素」,而不仅是第一个 li。
常见陷阱:
- HTML 中列表前有注释
<!-- intro -->→li不再是 first-child - 父元素内混用了其他标签,例如:
<ul> <p>说明</p> <li>第一项</li> </ul> - 使用了
display: contents或 flex 容器中子项被包裹导致结构变化
更稳妥的选择:用 :nth-of-type(1) 或 :nth-child(1 of li)
如果父容器里只有 li 是你关心的类型,:nth-of-type(1) 更可靠——它只看同类型元素的顺序,忽略其他标签干扰。
现代浏览器(Chrome 119+、Firefox 120+、Safari 17.4+)已支持 :nth-child(1 of li),语义最清晰:「在所有 li 中排第一的那个」。
示例:
ul li:nth-child(1 of li)::before {
content: "★";
margin-right: 8px;
color: #e67e22;
}
装饰图标要对齐,别只靠 margin
纯文字 + ::before 图标容易上下错位,尤其字体不一致时。关键不是加 vertical-align,而是统一基线参考。
- 给
li设置line-height(如1.5),再让伪元素继承 - 用
transform: translateY(-0.1em)微调位置,比vertical-align: middle更可控 - 避免用
font-size过大导致图标撑高行高;建议用em或rem单位保持缩放一致性
图标用字体还是 SVG?取决于加载与定制需求
如果只是简单符号(✓、★、→),用 Unicode 字符最轻量;需要颜色渐变、动画或高清缩放,就得上 inline SVG。
SVG 写法示例(嵌入 ::before):
li:nth-child(1 of li)::before {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2327ae60' d='M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z'/%3E%3C/svg%3E");
margin-right: 8px;
display: inline-block;
width: 1em;
height: 1em;
vertical-align: -0.25em;
}
注意 URL 编码和 vertical-align 配合,否则 SVG 容易下沉。
真正麻烦的是动态内容——比如 JS 插入新 li 后,首个项变了但样式没重算。这时候不能只靠 CSS,得配合 class 控制或重新触发渲染。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











