最后一项仍有下划线是因为:last-child未匹配到目标li,而是被末尾的空文本节点、注释或其它元素占据;下划线还可能源于父容器border-bottom、text-decoration继承或溢出渲染。

直接用 li:not(:last-child) 加下划线,最后一项自动不显示——但前提是结构干净、浏览器支持、样式没被覆盖。
为什么 li:not(:last-child) 加下划线后最后一项还有线?
不是选择器写错了,而是它根本没匹配到你认为的“最后一个 li”:
-
:last-child匹配的是父元素中**最后一个子节点**,如果末尾有空格文本节点、注释、<hr>或隐藏的li(display: none),:last-child就会落在那个节点上,导致所有li都满足:not(:last-child) - 下划线可能来自父容器的
border-bottom或继承的text-decoration,而不是你写的那条规则 - 若用了
text-decoration: underline,注意它会向下“溢出”行高,视觉上像多了一条线;而border-bottom是精确控制的
怎么写才真正只给前 N−1 项加下划线?
优先按场景选写法,别硬套通用模板:
- 纯
ul > li结构(无干扰节点):ul li:not(:last-child) { border-bottom: 1px solid #999; } - 混有其他标签(如
<p>、<div>)或不确定 DOM 是否干净:ul li:not(:last-of-type) { border-bottom: 1px solid #999; }—— 它只看li类型内的顺序 - 需要兼容 IE8(已极少见):
ul li { border-bottom: 1px solid #999; } ul li:last-child { border-bottom: none; },但得确认 IE8 能识别:last-child(仅 IE9+ 原生支持,IE8 需 JS 补丁) - Flex/Grid 布局中视觉顺序被
order打乱:li + li更可靠——它选中“前面紧挨着一个li的li”,天然跳过第一个,且不受 DOM 顺序干扰
用 text-decoration 还是 border-bottom?
二者行为差异大,选错会导致对齐错位、响应式失效:
立即学习“前端免费学习笔记(深入)”;
-
text-decoration: underline是基于字体基线渲染的,受line-height、font-size、缩放影响明显;移动端高 DPI 下容易模糊或双线 -
border-bottom是像素级可控的,配合box-sizing: border-box和transform: scaleY(0.5)(针对 1px 细线)更稳妥 - 若必须用
text-decoration,清除继承:ul li:not(:last-child) { text-decoration: underline; } ul li:last-child { text-decoration: none; },且确保父元素没设text-decoration
真正麻烦的从来不是写哪一行 CSS,而是打开开发者工具,点开那个“最后一项”,看 computed 样式里 :last-child 究竟命中了谁——DOM 结构比想象中更脆弱。


















