最直接可靠的做法是使用 css columns 属性作用于 容器,如 columns: 2; column-gap: 1.5em,实现两列并排且序号自动连续、语义正确、可访问性良好。

用 CSS columns 实现 ol 两列并排最直接
HTML 原生 <ol></ol> 不支持“每行两个列表项”这种网格式排列,强行用 display: flex 或 grid 会破坏序号逻辑(比如第 1、2 项在第一行,但浏览器仍按顺序渲染,序号不会重置或分组)。真正可靠且语义正确的做法是用 CSS 多列布局(columns),它让内容流式分栏,序号自动连续,且兼容性好(Chrome 50+、Firefox 50+、Safari 9+、Edge 10+)。
关键点:columns 是作用在 <ol></ol> 容器上的,不是给 <li> 单独设样式。
<ol style="columns: 2; column-gap: 1.5em;"> <li>第一项</li> <li>第二项</li> <li>第三项</li> <li>第四项</li> </ol>
-
columns: 2指定分两栏,等价于column-count: 2 -
column-gap: 1.5em控制栏间距,避免文字挤在一起 - 不要设置
height或overflow: hidden,否则可能截断内容 - 若列表项内含块级元素(如
<p></p>、<div>),需加 <code>break-inside: avoid防止跨栏断裂flex 或 grid 为什么不适合 ol 的序号需求
很多人试过给
<ol></ol>设display: flex并用flex-wrap,或者用display: grid+grid-template-columns: repeat(2, 1fr),结果发现:序号还是 1、2、3、4……但视觉上变成「1 2」在上行、「3 4」在下行——这看似满足要求,实则埋了坑:- 屏幕阅读器仍按 DOM 顺序读出全部序号,无法感知“两列”结构,可访问性受损
- 打印时通常回退为单列流式布局,序号和内容错位
- 如果后续加 JS 动态插入
<li>,flex/grid 不保证新项插入位置符合预期列顺序 -
<ol></ol>的start属性、reversed等行为在 flex/grid 下可能异常
需要精确控制每列项数?得拆成两个 ol
如果业务逻辑明确要求「左列固定 3 项,右列放剩下所有」,或者要支持响应式断点(比如小屏单列、中屏双列、大屏三列),
columns就不够用了——它只按高度均分内容,不按项数切分。这时只能手动拆分 DOM:
<div class="ol-split"> <ol start="1"> <li>第一项</li> <li>第二项</li> <li>第三项</li> </ol> <ol start="4"> <li>第四项</li> <li>第五项</li> </ol> </div>- 用
start属性确保序号连续 - 外层
<div> 用 <code>display: flex或grid排列两个<ol></ol> - 注意:这种方式失去原生
<ol></ol>的语义完整性,需额外加 ARIA 标识(如role="list")提升可访问性 - 给
<li>加break-inside: avoid(或-webkit-column-break-inside: avoid)强制整项不跨栏 - 搭配媒体查询,在小屏切回单列:
@media (max-width: 600px) { ol { columns: 1; } } - 避免在
<li>内使用height、position: absolute等破坏文档流的样式 - 测试时打开开发者工具的「Rendering」面板,勾选 “Emulate CSS columns”,看是否意外换栏
移动端适配和常见断裂问题
用
columns时,小屏下容易出现单个<li>被硬生生切成两半(上半在左栏、下半在右栏),尤其当列表项含图片或长段落时。columns就是最省心的选择。但一旦涉及 SSR 渲染、SEO 抓取或无障碍审核,就得格外留意break-inside和响应式降级逻辑——这些细节不报错,但上线后才暴露。











