用 border-bottom + :last-child 最省事可靠:每项设 border-bottom: 1px solid #e0e0e0,再用 li:last-child { border-bottom: none; } 去末线,兼容 IE9+,DOM 与视觉顺序一致时完全可靠;避免混用 margin-bottom 和 border-bottom 导致留白不均。

用 border-bottom + :last-child 最省事可靠
垂直列表(flex-direction: column)加分割线,直接给每项设 border-bottom: 1px solid #e0e0e0,再用 li:last-child { border-bottom: none; } 去掉最后一根线。这个组合兼容 IE9+,DOM 顺序和视觉顺序一致时完全可靠。
常见错误是混用 margin-bottom 和 border-bottom:前者控制项间距,后者画线,两者叠加会导致底部留白不均。建议统一用 margin-bottom 控制间距,border-bottom 只负责线条本身。
- 确保父容器是
display: flex; flex-direction: column; - 不要在
li上设padding-bottom来“抬高”边框——这会让最后一项底部空白异常 - 如果列表项有
display: none或 JS 动态增删,:last-child仍选 HTML 中最后一个元素,不是视觉末尾
横向菜单用 border-right 比 margin-right 更稳
Flex 横向菜单(flex-direction: row)里,margin-right 容易在响应式换行或 justify-content: space-between 下导致右侧多出空白、甚至触发换行;border-right 不占布局空间,且能精准控制“哪几项之间有线”。
写法很简单:a { border-right: 1px solid #e0e0e0; } + a:last-child { border-right: none; }。注意必须配合 box-sizing: border-box,否则边框会撑宽总宽度,在固定容器中引发溢出或换行。
立即学习“前端免费学习笔记(深入)”;
- 避免用
:not(:last-child)——语义等价但部分旧版 Safari 解析略慢 - 若菜单必须换行(
flex-wrap: wrap),:last-child失效,此时改用gap: 8px(现代浏览器)或margin-right配合flex: 0 0 calc(25% - 8px)更稳妥 - 文字高度不一致时,
border-right会自动对齐容器顶部,比伪元素定位更省心
用伪元素 ::after 实现不干扰布局的分割线
当需要线不顶满上下边缘、或要兼容高 DPI 设备(如 iPhone)时,border 容易模糊或变粗,这时用 ::after 绝对定位更可控。关键点不是“怎么画线”,而是“怎么不让它抢位”。
每个子项设 position: relative; min-width: 0;,然后:&::after { content: ""; position: absolute; right: 0; top: 0; bottom: 0; width: 1px; background: #e0e0e0; margin: auto 0; }。其中 min-width: 0 是 Safari 和旧 Chrome 的必填项,否则 flex-grow 撑不开空间,线会错位或消失。
- 高 DPI 下别用
background画 1px 线,改用box-shadow: 1px 0 0 #e0e0e0,更锐利 - 不要只写
flex-grow: 1,伪元素需flex: 1(即flex-basis: 0)才能均分剩余空间 - 若子项内含长文本,加
overflow: hidden防止内容撑破布局
响应式换行后分割线错位怎么办
flex-wrap: wrap 时,:last-child 仍指 DOM 最后一个元素,不是每行末尾。结果就是某行中间出现“断线”,或末尾多出一根线——这不是 bug,是选择器逻辑使然。
真正在换行场景下可靠的解法只有两个:gap(推荐)或精确控制 nth-child。比如三列布局,用 .item:nth-child(3n) { border-right: none; } 清除每行最后一项的右线;四列就换成 4n。但前提是列数固定、DOM 顺序严格。
-
gap: 12px是最干净的方案,现代浏览器支持良好,完全避开边框逻辑 - 如果必须支持老浏览器,放弃
border-right,改用margin-right+flex: 0 0 calc(25% - 12px),再用:nth-child(4n)清除每行末尾 margin - 千万别用
transform: scaleY(0.5)缩放 1px 边框——subpixel 渲染会导致模糊,尤其在滚动时


















