D02 响应式文章列表
D02 响应式文章列表
摘要:文章列表页面的结构固定:标题、筛选、卡片网格、分页。难点在网格的自适应——固定列数在窄屏挤压、在宽屏留白;
auto-fit加minmax能让列数随宽度自动变化。本文给出列表页完整布局、两处容器查询与六项验收。
关键词:列表页,自适应网格,断点,分页,容器查询
所属:frontend/css / D-实战 | 上一篇:D01-组件样式按钮与卡片 | 下一篇:D03-暗色主题与设计令牌
1 引言
列表页的布局目标只有一个:不论宽度多少,卡片都不被挤压、不留大片空白、不出现横向滚动。
本文给出一份可直接复用的列表页样式。范围见表 1-1。
| 项 | 本文覆盖 | 本文不覆盖 |
|---|---|---|
| 结构 | 页头、筛选、网格、分页 | 数据加载与筛选逻辑 |
| 网格 | auto-fit + minmax、容器查询 |
瀑布流布局 |
| 细节 | 卡片等高、摘要对齐、分页状态 | 无限滚动 |
2 预备知识
| 项 | 要求 | 核对方式 |
|---|---|---|
| 环境 | 本地服务器可用 | 浏览器能打开 localhost |
| 文件 | css-practice/list.html |
含 9 张卡片结构 |
| 前置 | D01 | 卡片样式已可用 |
| 前置 | A07、A08 | 网格与断点 |
3 原理与实现
3.1 列数由可用宽度决定
不再为每个断点写列数,而是给出「最小可接受卡片宽度」,由浏览器算列数,如图 3-1 所示。
flowchart LR
A["可用宽度 W"] --> B{"auto-fit + minmax(18rem, 1fr)"}
B --> C["列数 = floor(W / 18rem)"]
C --> D["剩余空间按 1fr 均分"]
D --> E["卡片等高、间距一致"]
图 3-1 自适应列数的计算方式
图上可见:卡片最小宽度是唯一需要维护的参数;容器变宽只增加列数,不改变卡片比例。
3.2 完整布局
/* 运行环境:Chrome 130+;css-practice/list.css */
.page {
max-inline-size: 76rem;
margin-inline: auto;
padding-inline: 1rem;
}
.page__head {
display: flex;
flex-wrap: wrap;
align-items: baseline;
justify-content: space-between;
gap: 0.75rem;
margin-block: 1.5rem 1rem;
}
.filters {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
list-style: none;
padding: 0;
margin: 0 0 1.5rem;
}
.filters a {
display: inline-block;
padding: 0.25rem 0.75rem;
border-radius: 999px;
background: var(--surface-alt, #f1f5f9);
text-decoration: none;
}
.filters a[aria-current="page"] { background: var(--brand, #1d4ed8); color: #fff; }
.list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
gap: 1rem;
list-style: none;
padding: 0;
margin: 0;
}
.list > li { display: grid; }
.card-wrap { container-type: inline-size; }
@container (min-width: 22rem) {
.card__title { font-size: 1.25rem; }
}
.pager {
display: flex;
justify-content: center;
gap: 0.5rem;
margin-block: 2rem;
list-style: none;
padding: 0;
}
.pager [aria-current="page"] { font-weight: 700; text-decoration: underline; }
布局要点见表 3-1。
| 项 | 写法 | 目的 |
|---|---|---|
| 网格 | repeat(auto-fit, minmax(min(18rem, 100%), 1fr)) |
列数自适应,窄屏不溢出 |
| 卡片等高 | 列表项 display: grid |
让卡片撑满行高 |
| 筛选状态 | aria-current="page" |
语义与样式同源 |
| 分页 | nav + ul,当前页标记 |
可读且可朗读 |
| 内边距 | 页面级 padding-inline |
小屏留白 |
实施清单:
| 步骤 | 动作 | 产出 |
|---|---|---|
| 1 | 写页面容器与最大宽度 | 大屏居中 |
| 2 | 写页头与筛选列表 | 筛选条可用 |
| 3 | 写自适应网格 | 列数随宽度变化 |
| 4 | 列表项设为 grid | 卡片等高 |
| 5 | 补容器查询调整标题字号 | 大卡片字号更大 |
| 6 | 写分页与当前页标记 | 状态可辨 |
| 7 | 按 4 节清单验收 | 六项通过 |
4 验证与讨论
- 从 360 像素拖到 1440 像素,记录列数变化:1 → 2 → 3 → 4。
- 检查任意宽度下是否有横向滚动条。
- 把某张卡片标题改为三行,确认同行其它卡片高度一致、内容不重叠。
- 检查筛选与分页的当前项,确认视觉与语义一致。
| 序号 | 验收项 | 判定标准 | 依据 |
|---|---|---|---|
| 1 | 列数自适应 | 宽度变化时列数按 1/2/3/4 变化 | 表 3-1 |
| 2 | 无横向滚动 | 任意宽度无滚动条 | 表 3-1 |
| 3 | 卡片等高 | 同行卡片高度一致 | 表 3-1 |
| 4 | 筛选状态 | 当前项与语义一致 | 表 3-1 |
| 5 | 分页可用 | 当前页可辨、链接可点 | 表 3-1 |
| 6 | 容器查询 | 宽卡片标题更大 | 3.2 节 |
五项取舍见表 4-1。
| 决策点 | 采用方案 | 备选方案 | 不选的理由 |
|---|---|---|---|
| 列数控制 | auto-fit + minmax |
三个断点写死列数 | 断点越多越难维护 |
| 卡片高度 | 列表项 grid 拉伸 | 固定 min-height |
固定值在长标题下仍会溢出 |
| 卡片最小宽 | 18rem | 12rem | 过窄时标题频繁换行 |
| 筛选状态 | aria-current |
额外 .active 类名 |
属性同时服务语义与样式 |
| 分页 | 静态列表 | 无限滚动 | 静态分页可检索、可直达 |
讨论与局限。 auto-fit 在卡片数量少时会拉伸卡片填满整行,需要保持统一宽度时应改 auto-fill。另容器查询需要每张卡片外层声明 container-type,层级多时会增加维护成本。
5 常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 窄屏出现横向滚动 | minmax 下限大于容器宽度 |
用 min(18rem, 100%) |
| 卡片高度参差 | 列表项未设 grid | 列表项 display: grid |
| 列数与预期不符 | 容器受 max-width 限制 |
检查外层宽度 |
| 筛选当前项看不出 | 只加了样式未加属性 | 用 aria-current="page" |
| 分页点不动 | li 内用了 span 而非 a |
用链接,当前页才用 span |
6 结论
| 序号 | 结论 | 依据 |
|---|---|---|
| 1 | 只维护卡片最小宽度,列数交给浏览器 | 图 3-1 |
| 2 | 卡片等高靠列表项 grid | 表 3-1 |
| 3 | 状态用属性选择器,语义与样式同源 | 表 3-1 |
| 4 | 静态分页优于无限滚动 | 表 4-1 |
- 上一篇:D01-组件样式按钮与卡片
- 下一篇:D03-暗色主题与设计令牌
- 返回:D00-总结 | 科目 README
参考文献
[1] MDN Web Docs · CSS Grid 自动填充,https://developer.mozilla.org/zh-CN/docs/Web/CSS/repeat(访问于 2026-10-31)
[2] web.dev · 响应式布局,https://web.dev/articles/responsive-web-design-basics(访问于 2026-10-31)

评论 0
还没有评论,快来抢沙发吧~