# 把博客列表变成画廊

> 用文章封面浏览博客，支持等高拼接、无缝和瀑布流，并为触屏与键盘保留完整的文字入口。

---

LLMS 索引： [llms.txt](/zh/llms.txt)

---

有时候，认出一篇文章最快的办法是看封面。旅行手记、速写集、项目记录，都可能
比普通技术文章更适合先看图、再读标题。

OINK 1.4.0 新增一种博客视图：`gallery`。每篇文章成为一张可点击的
封面，默认按比例拼成行；鼠标悬停或键盘聚焦时，标题和描述浮现出来，点击则
进入文章。

> [!NOTE] 已随 OINK 1.4.0 发布
> 画廊已经属于正式主题。它沿用普通博客文章模型，只增加一种以封面浏览同一批文章的方式。

## 同一批文章，四种浏览方式 {#four-views}

现有的几种视图各有用途。知道日期或标题时，表格最便于查找；想先读摘要，
水平条目更从容；卡片把封面和文章信息放在一起。画廊则把大部分空间留给封面。

| 博客视图 | 读者看到什么 |
| --- | --- |
| `list` | 带缩略图、元数据和摘要的水平条目 |
| `cards` | 带 16:9 封面与文章信息的规则卡片网格 |
| `table` | 紧凑的日期、标题、标签行 |
| `gallery` | 按比例排布的封面，附带标题和简短描述 |

开启布局切换后，四种视图显示同一页文章，日期顺序与分页结果一致。读者可以先
看封面，再切成表格查找，不必重新翻到另一页。关闭切换器时，独立表格仍保留
原来的行为：一次列出整个栏目。

## 借用 Expo 的排布 {#borrowing-expo}

[Expo](/zh/docs/write/expo/) 已经有图片展墙。博客画廊复用它的行布局算法和
紧凑的控制方式，内容仍取自普通博客页面：特色图片作为封面，页面标题作为
名称，description 提供描述。作者无需再维护一份相册清单。

点击后的去向也要符合读者预期。Expo 的图片打开查看器，博客封面进入文章；
设置了 `manual_link` 的文章仍然前往外部地址。这样，画廊可以作为写作内容的
索引，也适合封面承担主要表达、正文只有几句话的视觉短记。

画廊内部提供三种排布：

| 排布 | 布局方式 | 文字显示 |
| --- | --- | --- |
| `wall` | 等高拼接，保留 6px 间隙 | 悬停或键盘聚焦时显示 |
| `seamless` | 使用相同的行布局，去掉间隙 | 悬停或键盘聚焦时显示 |
| `cards` | 每个条目放入当前最短的一列，形成瀑布流 | 始终显示在图片下方 |

这里的 `cards` 是画廊里的瀑布流，与博客外层的规则卡片视图区分开。旁边的
滑杆可以在 160–360 CSS 像素之间调整目标图片大小。画廊独立记忆这些选择，
不会因为改了博客列表，就把下一页的 Expo 相册也换一种排法。

## 给手机上的文字留出空间 {#touch-and-focus}

只能悬停才出现的描述，在触摸屏上几乎没有用。没有精细指针与悬停能力的设备，
会把展墙和无缝模式的文字放在图片下方。排版时，每一行还会留出最高一块文字
所需的空间，避免下一行盖住链接或正文。

超长竖图需要额外处理。如果窄屏格子完全遵循原图比例，下面的文字可能每行只
放得下几个字。画廊宽度低于 500px 时，我们会进一步收紧格子的宽高比范围。
图片仍在格子里完整显示，必要时留白。这是在封面不裁切与文字可读之间做的取舍。

键盘聚焦会显示与悬停相同的说明，并画出格子内侧的焦点环。链接以文章标题
作为无障碍名称。没有封面的文章保留可点击的标题块，图片加载失败时也采用
相同回退。即使禁用 JavaScript，页面仍是一份带有可见文字和普通链接的
响应式网格。

## 为栏目开启画廊 {#enable-gallery}

在博客栏目的 `_index.md` front matter 中加入：

```yaml {title="content/blog/_index.md"}
blog_index: gallery
blog_index_toggle: true
blog_index_size: 24
blog_gallery:
  mode: wall
  size: 240
```

`blog_index` 决定初始视图。`blog_index_toggle` 允许读者循环切换四种视图，
设为 `false` 就只发布画廊。`blog_index_size` 控制每页文章数，
`blog_gallery.size` 控制目标格子大小，两者各管一件事。

如果想设成站点默认值，将这些键放入 `params.ui`：

```yaml {title="hugo.yml"}
params:
  ui:
    blog_index: gallery
    blog_index_toggle: true
    blog_index_size: 24
    blog_gallery:
      mode: wall
      size: 240
```

页面或栏目 cascade 可以覆盖站点默认值。`blog_gallery` 块会整体替换站点块，
因此希望保留两个设置时，要把两个字段一起写上。封面继续使用页面包里的
特色图片或已有的 `images` 字段。

上述配置适用于主题自带的博客栏目索引；自定义首页和术语页模板若需展示画廊，
需要显式调用画廊 partial。

## 保持实现简单 {#implementation}

主题会把可处理的大封面缩放到 960 × 960 范围内，保留原图比例；GIF 封面使用
静帧预览。图片采用延迟加载，隐藏视图首次显示时也沿用这个机制。本地封面
不需要远程图片服务，也不增加浏览器端依赖。

画廊有自己的小型运行时，复用 Expo 的几何计算。当视图重新显示、可用宽度
改变、字体加载完成，或图片实际尺寸确定后，都会重新计算布局。这些变化比
第一张截图更值得检查：初次打开没问题的页面，可能在拖动侧栏或切换视图后
发生重叠。

检查器会比较四种视图和不同分页中的文章顺序。浏览器回归覆盖中英文、桌面
与触屏、浅色与深色、键盘操作、缺失封面、图片加载失败及禁用 JavaScript。
完整参数见[博客创作指南](/zh/docs/write/blog/#list-gallery)，内容模型与实现
归属记录在[设计决策](/zh/docs/design/decisions/blog-gallery/)中。

---

反链：

- [博客画廊](/zh/docs/design/decisions/blog-gallery/)
