CSS Grid 是实现真正可控双栏列表的最佳方案,直接在 ul 上设置 display: grid、grid-template-columns: 1fr 1fr 和 gap 即可,配合媒体查询响应式切换单栏,语义清晰、高度自适应、现代浏览器全面支持。

用 CSS Grid 实现真正可控的双栏列表
HTML 本身没有“双栏列表”这个原生概念,ul 和 li 只负责语义化地表达“一组并列项”,列数、换行、对齐全靠 CSS 控制。Grid 是目前最直接、最不易出错的方式,尤其适合信息流类内容(比如博客摘要、卡片式资源、打卡记录)。
常见错误是强行用 float 或两层 ul 拆分数据——这会让 DOM 结构和逻辑脱节,后续加筛选、分页、响应式都容易翻车。
- 直接在
ul上设display: grid,用grid-template-columns: 1fr 1fr定义两等宽列 - 加
gap: 1rem控制项间距,比用margin更干净 - 如果项高不一致(比如有的带图、有的纯文字),加
grid-auto-rows: minmax(100px, auto)防止错位 - 移动端想变单栏?加媒体查询:
@media (max-width: 768px) { grid-template-columns: 1fr; }
Flex 布局也能做,但要注意 wrap 行为
Flex 更轻量,适合简单场景,但默认是“一行排不满就换行”,不是严格按列切分。如果你希望第 1、3、5… 项总在左列,第 2、4、6… 总在右列(即“奇偶列固定”),Flex 不适合——它只管顺序流,不管物理列位置。
典型误用:给 ul 设 display: flex; flex-wrap: wrap,再给 li 设固定宽度(如 width: 48%)。问题在于:当某项内容超长或图片加载失败时,宽度计算可能失准,导致最后一行只剩一列或错位。
- 若坚持用 Flex,推荐
flex-basis: calc(50% - 0.5rem)配合gap,避免 margin 干扰换行判断 - 必须加
box-sizing: border-box,否则 padding/border 会撑破列宽 - IE11 不支持
gap,得退回到margin+ 负边距 hack,不建议新项目兼容
不要用 float 或 inline-block 模拟双栏
这两种方式在信息流场景下几乎必然出问题:float 需要清除浮动,inline-block 有看不见的空白字符占位。更麻烦的是,它们无法响应内容高度变化——左边一个长卡片,右边一堆短条目,视觉上就会严重不对齐,且无法用 CSS 精确控制对齐基准线。
实际开发中,这类布局一旦加了 JS 动态插入新项(比如无限滚动加载),float 和 inline-block 的重排行为极难预测,调试成本远高于初期多写几行 Grid 代码。
- 所有现代浏览器(Chrome 66+、Firefox 61+、Safari 12.1+、Edge 79+)都完整支持
grid-template-columns - 如果你的项目需支持 iOS Safari 10.3 以下(已极罕见),才需 fallback 到 Flex
- 别为了“看起来像两列”而牺牲语义结构——
ul就是单个逻辑列表,拆成两个ul会让屏幕阅读器误读为两个独立列表
信息流卡片的实际 HTML 结构示例
重点不是“怎么让两列看起来整齐”,而是“怎么让数据结构、可访问性、响应式三者同时成立”。下面这个结构经得起检查:
-
打卡记录
今天完成了听力训练
-
资源更新
新增 K2 歌曲 12 首
-
精听练习
Level 3:跟读+填空
-
学习反馈
家长上传语音作业
对应 CSS 只需四行:
.card-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.25rem;
}
@media (max-width: 768px) {
.card-grid { grid-template-columns: 1fr; }
}
真正的复杂点不在写法,而在你是否意识到:信息流的“列”是视觉呈现层,不是数据组织层。一旦把“分两列”当成数据逻辑来处理,后面加搜索、排序、状态标记(如“已打卡”角标)时,就会反复推翻重来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











