:last-child 不生效是因为父容器中存在空格、换行、注释等非 li 子节点,导致 li 不是最后一个子元素;应改用 li:last-of-type 或更健壮的 li + li 相邻兄弟选择器。

为什么 :last-child 有时不生效?
常见现象是给列表项加了 border-bottom,再用 li:last-child { border-bottom: none; } 想去掉最后一项的线,结果没去掉。原因通常是:父容器里除了 li 还有其他节点(比如空格、换行符、注释或 script 标签),导致最后一个 li 并非父元素的 :last-child —— 它只是 :last-of-type。
- HTML 中换行和缩进会生成
Text节点,它们也是“子元素” -
:last-child匹配的是 DOM 树中**位置最靠后的那个子元素**,不是类型最末的那个 - 若父元素末尾有注释
<!-- end -->,li就永远成不了:last-child
更可靠的写法:用 :last-of-type 替代
如果列表结构固定为 ul > li 或 ol > li,直接改用 li:last-of-type 更稳妥,它只看元素类型,无视中间夹杂的文本或注释节点。
li {
border-bottom: 1px solid #ddd;
}
li:last-of-type {
border-bottom: none;
}
注意::last-of-type 在 IE9+ 支持,现代项目基本无兼容问题;但若列表里混用 li 和 div(比如某些 CMS 输出),它仍可能失效 —— 此时得靠 JS 或重构 HTML。
用相邻兄弟选择器 li + li 反向加线
这是最健壮的方案:不给所有 li 加边框,而是只给**后面还有兄弟元素的 li** 加上边框。这样天然避开末项,完全不依赖“最后一个是谁”。
li {
border-bottom: none;
}
li + li {
border-top: 1px solid #ddd;
}
这个写法:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
- 对 DOM 结构零敏感,空格、注释、动态插入都无影响
- 支持任意顺序渲染(比如倒序列表、虚拟滚动)
- 性能更好 —— 浏览器不用反复计算“谁是最后一个”
- 若需分隔线在下方,把
border-top换成margin-top或padding-top即可
Flex/Grid 布局下别硬套 :last-child
当列表用 display: flex 或 display: grid 排版时,:last-child 依然按 DOM 顺序判断,但视觉顺序可能被 order 属性打乱。此时视觉末项 ≠ DOM 末项。
例如:
- B
- A
- C
视觉顺序是 A-B-C,但 DOM 顺序仍是 B-A-C,li:last-child 匹配到的是 C(正确),而 li:last-of-type 也匹配 C —— 看似没问题。但一旦加入 flex-wrap 多行布局,或使用 grid-template-areas,就极易出错。
结论:Flex/Grid 场景下,优先用 li + li 方式,或者用 JS 动态标记视觉末项。
真正麻烦的不是选哪个伪类,而是默认假设“HTML 结构干净”——实际项目里,模板引擎、CMS、SSR 注入、甚至 Prettier 自动格式化,都会悄悄往节点间塞空白字符。盯着 :last-child 调十分钟不如换一行 li + li。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










