用 li:not(:last-child) { border-bottom: 1px solid #eee; } 可精准为通栏列表每项加底部分割线且自动排除最后一项,语义清晰、兼容性好、无需js干预,动态增删列表时仍可靠生效。

怎么让通栏列表每项下面都有分割线,但最后一项不显示?
直接用 border-bottom 给每个 li 加线最简单,但末尾会多出一条多余线——这是初学者最常卡住的地方。根本原因是没排除最后一项,而不是 border 本身有问题。
推荐方案:用 :not(:last-child) 精准控制,比给最后一项设 border-bottom: none 更可靠(尤其当列表动态增删时)。
-
li:not(:last-child) { border-bottom: 1px solid #eee; }—— 最干净,语义明确 - 避免用
li:nth-last-child(n+2)这类写法,可读性差且容易算错 - 如果列表项是
div或其他容器,把li换成对应选择器即可,逻辑不变
为什么用伪类比在 HTML 里手动加 class 更稳妥?
因为真实项目中列表数据往往来自接口或循环渲染(比如 Vue 的 v-for、React 的 map),你没法提前知道哪一项是“最后一个”,更不能靠 JS 去动态加 class。
伪类是浏览器原生计算的,DOM 变了它自动重算,完全解耦。
立即学习“前端免费学习笔记(深入)”;
- JS 手动加
no-border类:需监听列表变化、处理首次渲染、防重复添加——不必要复杂 - 服务端模板(如 EJS、Jinja)里用
loop.last判断:只适用于静态首屏,SPA 场景失效 -
:not(:last-child):零成本、无副作用、兼容到 IE9+
border-bottom 分割线和 padding-bottom 冲突怎么办?
常见现象:线看起来“飘”在文字下面、离文字太远,或者和其他元素间距不一致。本质是 border-bottom 占据空间,但没被视觉感知到。
关键点:border 是盒模型的一部分,它会影响元素高度,但默认不参与行高计算。
- 给
li设padding-bottom: 8px时,实际高度 = 内容高 + 8px + border 宽度 → 可能撑开间距 - 更稳的做法:统一用
padding-bottom: 8px,然后把border-bottom当作视觉装饰,不依赖它撑开距离 - 如果必须用 border 控制间距,改用
margin-bottom: 1px配合border-bottom: none,再单独给线用伪元素画(见下条)
需要更灵活的分割线样式(比如虚线、带图标、渐变)怎么办?
border-bottom 只支持纯色实线/虚线/双线等基础样式,想加图标、阴影或渐变就得换思路。
用 ::after 伪元素替代 border 是标准解法,自由度高且不影响布局流。
li:not(:last-child)::after { content: ""; display: block; height: 1px; background: linear-gradient(90deg, #eee, #ccc, #eee); margin-top: 8px; }- 图标分割线:
content: "•"; color: #999; font-size: 12px; text-align: center;,再配line-height居中 - 注意:伪元素默认是 inline,必须设
display: block才能控制宽高










