应使用 li + li { margin-left: 12px; },它从第二个 li 开始添加左边距,不依赖伪类、兼容 IE7、避免混杂子节点导致的误判,是处理列表间隔最稳妥的方案。

为什么 :not(:last-child) 不能直接排除最后一个 <li>
很多人试过写 li:not(:last-child) { margin-right: 10px; },发现它确实能给除最后一个外的所有 <li> 加右边距——但前提是这些 <li> 的父容器里**只有 <li> 元素**。一旦父元素里混有其他类型子节点(比如注释、文本节点、<div>),<code>:last-child 就可能匹配不到真正的最后一个 <li>,导致误判。
:not(:last-of-type) 更可靠,但仍有前提
:last-of-type 只看同类型标签(比如只比对 <li>),不关心中间有没有其他标签,所以比 :last-child 更适合列表场景。但要注意:
- 它依赖 HTML 中
<li>的实际 DOM 顺序,如果最后一个是<li>,那li:not(:last-of-type)就生效 - 如果列表末尾被插入了
<li class="divider">这类“伪结尾”,它也会被当成最后一个<li>,导致前面的正常项被错误排除 - IE9+ 支持
:last-of-type,但 IE8 及更早版本完全不支持:not()和所有::类型伪类
真正稳妥的做法:用 :first-child 反向控制间隔
与其费力排除最后一个,不如给第一个之后的所有项加左边距(或上边距),这样天然避开结尾问题。这是 CSS 中处理“n-1 个间隔”的惯用思路:
ul li {
margin-left: 0; /* 重置默认 */
}
ul li + li {
margin-left: 12px;
}这个写法等价于 “从第二个 <li> 开始,每个都加左边距”,不依赖任何伪类兼容性,连 IE7 都支持。同理,垂直布局可用 li + li { margin-top: 8px; }。
立即学习“前端免费学习笔记(深入)”;
如果必须用 :not(),优先选 :not(:nth-last-child(1))
:nth-last-child(1) 和 :last-child 行为一致,但它在 :not() 中的解析更稳定(尤其在某些旧版 WebKit 内核中)。不过仍存在和 :last-child 相同的混杂子节点风险。可作为备选,但别迷信它比 :last-of-type 更强:
-
li:not(:nth-last-child(1))→ 排除的是“整个父容器中最后一个子元素且恰好是<li>”的项 - 如果父容器最后是
<p></p>,那所有<li>都不会被排除,结果反而错 - 真正需要的是“最后一个
<li>”,不是“最后一个子元素是<li>”——这点最容易混淆
复杂列表结构下,靠伪类精准定位“最后一个同类元素”本身就有模糊边界,这时候用兄弟选择器(+ 或 ~)往往比堆砌 :not() 更直白、更可控。


















