跳到正文

为什么我又把个人网站重做了一遍

Quarto
建站
从模板到自定义主题:一次关于「少一点装饰,多一点阅读」的重构,以及最后留下来的几条规则。
作者

橙照

发布于

2026年10月18日

上一版网站用了现成模板。它不难看,也能用,但每加一个页面,我都得先猜模板的类名是什么意思,再决定要不要覆盖。几个月后,样式文件里堆满了 !important,而我仍然说不清首页那三栏在手机上是怎样折行的。

这次重做,我给自己定了三个约束:

前两条是技术选择,第三条是验收标准。它们决定了后面的很多细节。

先定阅读路径,再画页面

上一版从“首页要放什么”开始,结果首页塞了自我介绍、最新文章、项目卡片、友链、订阅框和一张很大的头像。每个模块都有一点用,但没有一个能让人停下來。

这次先写了一个只有五行的草稿:

我是谁 → 我做过什么 → 我最近在想什么 → 怎么联系我。

对应的就是首页的顺序:一句主张、三个事实、项目、笔记、关于、联系。导航只保留这四件事,其他链接放进页脚。页面少了,反而更容易把每一屏做清楚。

主题不是换一套颜色

最容易做的事是改 --bs-primary,然后宣布“自定义主题完成”。真正麻烦的是那些模板没管的地方:标题的中英文混排、代码块的横向滚动、深色模式下的边框对比度、目录在窄屏上的位置。

我把样式分成两层:

  1. 变量层:颜色、字体、圆角、阴影、容器宽度,全部放在 tokens.css;
  2. 规则层:导航、首页、内页、页脚各自一个文件,只使用变量,不写死颜色。

这样深色模式不需要复制一套规则。只要在根元素上切换 data-theme,再让 Quarto 自己的 quarto-dark 类跟上:

html[data-theme="dark"] {
  --cz-bg: #14110e;
  --cz-ink: #f4ead9;
  --cz-accent: #e98a5c;
}

颜色不是越多越好。浅色模式用暖纸色做底,正文是偏暖的墨色;强调色只留给链接、按钮和少量标记。深色模式不是简单反色,而是把纸换成深棕,把橙色提亮,避免纯黑背景上的细字发虚。

Quarto 帮了大忙,也有自己的脾气

Quarto 的网站项目很适合这种站点:Markdown 写内容,YAML 管导航,Bootstrap 处理栅格,发布到 GitHub Pages 只需要一个 action。但它不是“零配置”。

我踩到的第一个坑是缩进。首页最初用原始 HTML 写,<div class="cz-hero"> 内部的空行和四空格缩进被 Pandoc 当成了代码块,整段 HTML 原样显示在页面上。后来改成 fenced div:

::: {.cz-hero}
...
:::

这里还有一条规则:::: 的上一行必须是空行,下一行也要空一行。否则 Pandoc 会把围栏当成普通段落的一部分。这不是 Quarto 的 bug,是 Pandoc 的 Markdown 解析规则;知道以后就不再浪费时间怀疑人生。

第二个坑是页面宽度。Quarto 的 page-layout: custom 不会自动把内容容器居中,默认贴着左侧。自定义页面需要自己处理:

#quarto-content.page-layout-custom {
  margin-inline: auto;
}

第三个坑是链接。Quarto 不会阻止你写一个不存在的 href,但构建时会给出警告。把警告当错误看,顺手就能发现导航里指向 .qmd 而不是渲染后路径的链接。

发布应该是一条命令

网站最终放在 GitHub Pages 上。构建和发布都在 GitHub Actions 里完成,本地只负责写和预览:

quarto preview
quarto render

发布工作流做三件事:安装 Quarto、渲染站点、把 _site 推到 gh-pages。第一次发布后,还要去仓库的 Settings → Pages 把来源改成 gh-pages。用户站点默认会指向 main,这一步很容易漏,漏了就会看到 404。

最后留下的检查清单

  • 每个页面都有独立的 title 和 description;
  • 导航链接在本地渲染后仍然有效;
  • 深色模式不是反色,而是重新检查过对比度;
  • 键盘可以到达所有交互元素,焦点环清晰可见;
  • 关闭动画后,内容仍然完整;
  • 发布后打开线上地址,而不是只看本地预览。

网站不是一次做完的。它现在仍然有一些我想改的地方,比如项目页的筛选、文章的上一篇/下一篇。但至少这次,我知道每一层为什么存在,也知道下一次该从哪里开始。

这篇之后:我把这套主题、检查清单和发布流程收进了 dsh-quarto-website 插件。如果你也想用 Quarto 做一个自己的站点,可以从那里开始,而不是从一堆互相覆盖的 CSS 开始。

回到顶部