Files
blog/docs/research/08-美化专项方案.md
T
wait4xandGLM-5.3 7c5455278b docs(research): 美化专项方案(文本轨,K-S 卡片,视觉待验标注)
现状审计 16 项(间距阶/灰阶档/圆角混用/流距/focus ring/代码块/
纸面板/热力图灰绿之争)× 5 站补充探索(rauno 12 级灰+paco alpha
阶梯+mattdesl 等宽层级+tw93 手写体温+antfu blur-up)× 卡片 K-S
(token 值级改法+computed-style 断言)× 截图问题清单 7 问(交
glm-5.3-flash:max 视觉轨复核中,verdict 合并后定案)。

验证: 截图床 /tmp/beauty-shots 25 张就位;文档 149 行入仓

Spec: none (方案文档文本轨,视觉裁定合并后呈审)

Co-authored-by: GLM-5.3
2026-10-26 22:55:05 +08:00

150 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 博客美化专项方案(视觉打磨批次)
> 侦察员 @agent-591c3f | 2026-10-26
> 证据链:仓库源码逐文件审计(tokens/global.css + 9 组件 + 2 文章页)× design/mockup.html 丙路线对照 × 本地重建 34 页实测(dist 内 Shiki 内联样式实抓)× WCAG 对比度数学计算 × 5 站补充抓取。
> 截图证据床 /tmp/beauty-shots/(22 张,1280×900 fullPage,SW 阻断,gz-server 18800 测试床):现状 12 张 `{home,reading,tech,books,gallery,moments}-{light,dark}.png`;mockup 基线 10 张 `mock-{home,reading,tech,gallery,moments}-{light,dark}.png`。
> 纪律分工:token 值/选择器/对比度数字=本报告结构性结论;"观感好坏"=⚠视觉待验,交视觉模型按 §5 问题清单复核,卡片产出不受阻。
## 0. 补充探索(每站聚焦视觉细节)
**抓取失败如实标注**:veselinov.pro、xivudong.me、photos.antfu.me 三域本机 DNS 无解析(getent 空记录,代理 7897 亦 000),已按任务预案换站并注明理由。
1. **rauno.me** ✅(HTML+2 CSS 实抓)——灰阶密度才是质感:stitches 体系 12 级灰(gray1–12 双主题 hsl 全套);间距阶严格 8px 步进(--space-1..11 = 8→88px);圆角三档 4/8/16+round;阴影三档全部 12% 黑透明(阴影当层级语言而非装饰);全站唯一动效曲线 `cubic-bezier(.2,.8,.2,1)`;focus-ring 变量化。字体=自研 X + JetBrains Mono + Georgia 点缀。
2. **paco.me** ✅(3 CSS 实抓)——灰阶走**黑/白 alpha 阶梯**(--black-a1..a12 = 5%–95% 共 12 档):灰由前景色透明度派生,暗色主题零重复维护;Newsreader 斜体做强调词是签名手法;字号全站仅 13/14/16/1.25rem/4rem 五档;边框唯一 `--border-thin:1px`;页边距 `max(24px, env(safe-area-inset-*))` 安全区与留白合一。
3. **mattdesl.com** ✅(换站理由见上)——全站等宽身份(BerkleyMono→Courier 回退)+ 97% 灰底/10% 墨字;标题 font-weight **normal**、统一 margin-top 1.5em——层级全靠字号与节奏不靠字重;标题小写化;标题锚 `#` 前缀常显;a:active 才变灰。与我们的 mono 轨同源:等宽当身份时,字重必须让位给间距。
4. **tw93.fun** ✅(替代 xivudong.me,DNS 失败)——body 15px,身份字体藏锋金楷 TsangerJinKai02(标题正文混排),中文个人站"手写体温"代表;内联 prefers-reduced-motion 全量豁免(与我们同款纪律);header 图标化导航。启示:中文身份字体走金楷/文楷一脉成立,我们 `--font-kai` 已在栈内,金句正是它的岗位。
5. **antfu.me/photos** ✅(photos 子域 DNS 失败,主域 /photos 200)——照片 img 带 inline `radial-gradient` **blur-up 占位**:图未加载先出主色近似色块,加载即有构图而非白洞;导航相机图标常驻;照片**无圆角无边框无阴影**直贴(摄影=内容本体不加框)。启示:图库质感优先做加载占位,而非边框阴影装饰。
## 1. 现状视觉审计(元素/现状/差距/目标)
| # | 元素 | 现状(源码事实) | 差距 | 目标 |
|---|---|---|---|---|
| 1 | 间距阶 | `--space-1..6`=4/8/16/24/40/64,跳档不均(缺 12/32) | rauno 8px 步进全阶 | 主阶不动,补正文流距 token(K) |
| 2 | 标题节奏 | `.prose-* h2/h3` 仅 margin-top 1.8/1.5em,**无下距**(global.css:69-79) | 标题贴死正文;mockup h2 为 `1.8em 0 .6em` | h2/h3 补下距(K) |
| 3 | 正文段距 | `p+p{margin-top:.9em}` 双轨 6 处字面量 | 不可一处调 | `--flow-*` token 化(K) |
| 4 | 灰阶层级 | ink-1..4+line 五档;**ink-4(2.52:1) 用于 13px 日期/图注正文级文字**(PostList row-date、tl-date、g-note)不达 AA;无 border-strong 档 | ink-3 5.09:1 达标;ink-4 应退纯装饰位 | ink-4 停用于文字,新增 `--line-strong`(L) |
| 5 | 圆角 | 4/6/8/10/12/999 字面量散落 7+ 处组件 | 未 token | `--radius-s/m/l` 三档(O) |
| 6 | 动效时长 | 0.15s/160ms/0.4s/0.6s/2.4s 与 `--dur:350ms` 并存;**且 `.postlist .row` hover 1px 上浮是死规则**(global.css:196 类名应为 `post-list`,dist 实证从未生效) | 时长纪律散 + 微交互断线 | 修死规则 + `--dur-fast/slow` 补阶(O) |
| 7 | 书评纸面板 | `.prose-reading` 仅上下 hairline + bg(global.css:52-63) | mockup 丙=全边框圆角卡(pad 44/radius 14)形态差 | 两案裁定(Q)⚠视觉待验 |
| 8 | 代码块 | Astro 默认 Shiki github-dark,dist 实测内联 `background:#24292e` **压过 token `--code-bg:#0d1117`**;无语言标签;`.term-dots` 为死选择器 | token 与实际分裂 | Shiki css-variables 主题接管 + 灰阶窗条 + 语言标签(P) |
| 9 | 表格 | global.css **零表格规则**;内容 3 篇含 markdown 表(dist 实证 `<table>` 裸渲染) | UA 默认裸表 | 分隔线制表格样式(R) |
| 10 | 列表 | reset `*{margin:0}` 后无 prose 列表规则;内容 5 篇含列表 | li 间距仅靠行高,紧贴 | li+li 间距 + marker 色(R) |
| 11 | 金句 | `.pull-quote` 全仓无使用(死选择器);blockquote 只有 A 墨线模式 | D 金句模式从未落地 | 写作指南模板 + mood 注入(Q) |
| 12 | 引文规则 | global.css 与 [...slug].astro:172-177 **镜像双份** | 漂移风险 | 单源化(Q) |
| 13 | 图库衬底 | `.stage` 仅 container-type,无背景 | mockup `--stage:#f4f4f2` 面板+radius 14 | 两案裁定(N)⚠视觉待验 |
| 14 | 页面标题 | books/gallery/moments 用 `--text-h1` 27px | mockup g-title 20px/700 | 降一档 22px 或保持(K)⚠ |
| 15 | 首屏 | IdCard=60px 渐变头像(紫→accent 彩色占位)+21px 名字,slot 被 socials 占用,**无身份陈述行** | mockup hero 有 bio 15px 行 | M 两案 |
| 16 | 热力图 | ink 灰四档(组件注释明示决策) | mockup 原型为绿四档 | S 裁定 ⚠视觉待验 |
| 17 | 达标项(不动) | 灯箱 backdrop 95%、focus ring 全局 2px、::selection 半透明、明暗双套 tokens、reduced-motion 全豁免(row hover 上浮除外——行 6 实锤为死规则) | — | 保持 |
## 2. 美化卡片(K–S,续 v2 A–J)
### K|正文流距 token 化与标题下距
- **目标**:标题-正文、段落-段落的呼吸成为可调参数;治愈 h2 贴正文。
- **改法**(tokens.css + global.css):新增 `--flow-p: 0.9em; --flow-h2-pre: 1.8em; --flow-h2-post: 0.6em; --flow-h3-pre: 1.5em; --flow-h3-post: 0.45em;`;global.css 双轨 h2/h3 改用变量并补 margin-bottom;`p+p` 改 `var(--flow-p)`。页面标题(Books/Gallery/Moments h1.page-title)27px→`--text-h2`(22px) 降档对齐 mockup g-title(视觉待验§5-6)。
- **涉及**:`src/styles/tokens.css`、`src/styles/global.css`、三页组件 `page-title` 规则。
- **验收**:playwright 断言 `.prose-tech h2` computed marginBottom ≈13.2px(22×0.6)、marginTop≈39.6px;`:root` `--flow-p`===' 0.9em';books 页 `h1.page-title` fontSize==='22px'。
- **工作量**:0.5d。
### L|灰阶达标与 border-strong
- **目标**:全部正文级文字 ≥4.5:1(WCAG AA 实测数:ink-3 亮 5.09/暗 5.22 ✓,ink-4 亮 2.52/暗 2.67 ✗);分隔线获得强弱两档。
- **改法**:PostList `.row-date`、MomentsPage `.tl-date`、GalleryPage `.g-note`、index `.lab` 的 `color: var(--ink-4)`→`var(--ink-3)`;tokens 新增 `--line-strong: #d4d6db` / dark `#3d434f`,供 kbd 边框、chip 选中态(现用 ink-3 充当)、TOC 选中线。ink-4 仅保留纯装饰(track 前方块、beat-dot)。
- **涉及**:tokens.css、PostList.astro、MomentsPage.astro、GalleryPage.astro、index.astro。
- **验收**:`.row-date` computed color==='rgb(107, 110, 120)';对比度数学 5.09:1;`--line-strong` 存在且 chip:checked border-color===rgb(212,214,219)。
- **工作量**:0.5d。
### M|首屏叙事两案(⚠视觉待验 §5-1 定案)
- **案1 极简维持+身份陈述**(推荐先行):IdCard 结构改两行——名字 21px 下加 `.idcard-bio`(15px/ink-3,一句身份陈述,文案用户定);socials 移到 bio 行下;头像渐变占位灰阶化(`--mood-3/accent` 渐变→`ink-3→ink-1` 灰渐变,真头像接入前不破纪律)。`margin-block` 40→56px 加呼吸。
- **案2 hero 强化**:头像 72px、名字 `--text-h1` 27px、bio 一行 mono 14px tagline(如 `阅读 · 技术 · 摄影`),首屏区块底加 `--line` 分隔。视觉重量↑,与"骨架克制"张力↑。
- **涉及**:IdCard.astro、Avatar.astro、index.astro。
- **验收**:案1 `.idcard-bio` 存在且 fontSize==='15px'、color===ink-3;头像 svg 首个 stop 颜色为灰阶(无 hue)。
- **工作量**:案1 0.5d / 案2 1d。
### N|图片质感与灯箱纯度
- **目标**:照片墙获得"策展台"层次而非散图直贴;灯箱进入"暗房"纯度。
- **改法**:tokens 新增 `--stage: #f4f4f2` / dark `#101318`(mockup 丙同位);GalleryPage `.stage` 加 `background: var(--stage); padding: var(--space-3); border-radius: var(--radius-l, 14px)`(⚠两案:有衬底 vs 无衬底,§5-4);新增 `--radius-img: 10px` 统一 .shot/.thumb/.mom-fig/prose img 圆角(现 8/8/8/10 混用);灯箱 backdrop `rgba(8,10,14,.95)`→`.97` + 底条 mono 字距 `0.02em`;blur-up 占位列观望(antfu 手法需管线配合,非纯 CSS)。
- **涉及**:tokens.css、GalleryPage.astro、MomentsPage.astro、index.astro、global.css。
- **验收**:`.stage` computed backgroundColor==='rgb(244, 244, 242)';`:root` `--radius-img` 存在且 `.thumb` borderRadius==='10px';dialog#lb backdrop 不便断言→断言 CSS 源含 0.97。
- **工作量**:1d。
### O|微交互 token 化与 focus ring 收尾
- **改法**:先修死规则——global.css `.postlist .row`→`.post-list .row`(hover 1px 上浮即刻复活);tokens 新增 `--dur-fast: 150ms; --dur-slow: 600ms;`;替换字面量——row hover `0.15s ease`→`var(--dur-fast) var(--ease)`、GalleryPage `#lb-img` 160ms→`var(--dur-fast)`、`.bg-glow` 0.6s→`var(--dur-slow)`、rise-in 0.4s→`calc(var(--dur) + 50ms)`;圆角 token:`--radius-s:6px; --radius-m:10px; --radius-l:14px`,全局字面量归位;`:focus-visible` 补 `border-radius: 2px`(mockup:29,防直角 outline 扎圆角钮)。
- **涉及**:tokens.css、global.css、Header.astro、GalleryPage.astro、各组件 radius 字面量。
- **验收**:`.post-list .row` computed transitionDuration==='0.15s' 且 hover 后 transform==='matrix(1, 0, 0, 1, 0, -1)' 且 timingFunction 含 'cubic-bezier(0.19, 1, 0.22, 1)';`:focus-visible` computed borderRadius==='2px';`grep -c 'px' radius 字面量` 下降(构建审计)。
- **工作量**:0.5d。
### P|代码块窗口化(Shiki 接管 + 语言标签 + 灰阶窗条)
- **目标**:`--code-bg/--code-ink` token 恢复统治(现被 Shiki 内联 #24292e 压制);代码块获得窗口身份。
- **改法**:astro.config.mjs `markdown.shikiConfig.theme: 'css-variables'`(Shiki 官方主题,颜色全走 `--shiki-*` 变量);global.css 定义 `--shiki-default/--shiki-key/...` 对齐现有 github-dark 色系但 bg/ink 用 `var(--code-bg)/var(--code-ink)`,亮暗同底纪律恢复;`pre.astro-code[data-language]::after{content:attr(data-language); …mono 11px; color:#8b949e; text-align:right; display:block}` 语言标签(零 JS,dist 实证 data-language 属性已在);窗条三灰点用 `pre::before{content:'';display:block;width:10px;height:10px;border-radius:50%;background:#3f4650;box-shadow:16px 0 0 #3f4650,32px 0 0 #3f4650;margin-bottom:8px}`(灰阶三档 `#3f4650/#4a515b/#565f6a` 递进,macOS 彩点不采——红线);pre padding 顶加 `6px`。删除 `.term-dots` 死规则。**行号不做**(短命令块为主,320px 移动端宽度宝贵,见 §4)。
- **涉及**:astro.config.mjs、global.css。
- **验收**:dist 文章页 `pre.astro-code` 无内联 background-color(`getAttribute('style')` 不含 'background-color');pre computed backgroundColor==='rgb(13, 17, 23)';`getComputedStyle(pre,'::after').content` 非 'none' 且含 attr;`getComputedStyle(pre,'::before')` width==='10px'。
- **工作量**:1d。
### Q|书评轨:纸面板形态 + 金句实装 + 引文单源
- **目标**:书评页的"纸感"从色块升级为形态;D 金句模式真正可用。
- **改法**:
- 纸面板两案:**A 卡化**=`.prose-reading{border:1px solid var(--paper-line);border-radius:var(--radius-l);padding:var(--space-5) clamp(20px,4vw,32px)}`(mockup sheet 形态);**B 维持通栏** hairline 仅把上下线升级 `--line-strong`。(⚠§5-2 裁定)
- 金句:内容约定 HTML 直书 `<blockquote class="pull-quote"><p>…</p><span class="quote-cite">——作者《书名》</span></blockquote>`(写作指南已有 raw HTML 先例);pull-quote 样式修 62px→`3.2em` 相对化 + `--mood` 从文章 frontmatter 经 [...slug].astro `article style="--mood:…"` 注入(现 PostList 已用同源 mood,接线一致);docs/写作指南.md 加模板一节。
- 引文单源:删除 [...slug].astro:172-177 镜像规则,markdown 裸 blockquote 全靠 global.css。
- **涉及**:global.css、pages/archives/[...slug].astro、en 同文件、docs/写作指南.md。
- **验收**:`grep -c 'blockquote' src/pages/archives/[...slug].astro`===0;含 pull-quote 的页面 computed fontFamily 含 'WenKai'、`::before` fontSize==='64px'(20×3.2);A 案 `.prose-reading` computed borderRadius==='14px'。
- **工作量**:0.5d。
### R|表格与列表基建(从零到精)
- **改法**(global.css,作用于 `.prose-reading/.prose-tech`):表格 `table{border-collapse:collapse;width:100%;font-size:.92em;margin-block:1.2em} th{text-align:left;font-weight:600;color:var(--ink-1)?→书评轨用 paper-ink} th,td{padding:6px 12px 6px 0;border-bottom:1px solid var(--line)} tbody tr:last-child>*{border-bottom:0} td{font-variant-numeric:tabular-nums}`——分隔线制,**不做 Zebra**(灰阶密度已够,见 §4);列表 `ul,ol{padding-left:1.5em;margin-block:1.2em} li+li{margin-top:.35em} li::marker{color:var(--ink-3)}`;tech 轨 kbd 已有样式保持。
- **涉及**:global.css(含 3 篇含表内容无需改动)。
- **验收**:tech 文章页 `th` computed borderBottomWidth==='1px';`li+li` marginTop≈6.65px(.35em@19px);`li::marker` color==='rgb(107, 110, 120)'。
- **工作量**:0.5d。
### S|热力图色系裁定(⚠视觉待验 §5-5)
- **现状**:ink 灰四档(hm-l1..4=ink-4..1),组件注释明示"灰阶纪律"决策;mockup 原型为 GitHub 绿四档。绿=贡献量语义直觉(外部认知零成本),灰=骨架纯度。
- **改法(若裁定换绿)**:tokens 新增 `--hm-0:#ebedf0/--hm-1:#9be9a8/--hm-2:#40c463/--hm-3:#30a14e/--hm-4:#216e39` + dark 套(#22272e/#0e4429/#006d32/#26a641/#39d353),Heatmap.astro 四行替换。默认建议**维持灰阶**(热力图是骨架层不是内容层;绿色块会成为首页唯一大面积彩色,重心被劫持)。
- **验收**:若换绿 `--hm-4`===' #216e39' 且 `.hm-l4` backgroundColor 对应;维持则零改动,S 卡关闭。
- **工作量**:0.2d。
## 3. 优先级(视觉收益 × 工作量)
| 卡 | 视觉收益 | 工作量 | 象限 |
|---|---|---|---|
| L 灰阶达标 | 高(可读性硬指标) | 0.5d | ★高收益低成本 |
| R 表格列表 | 高(3+5 篇内容直接受益,现裸样式) | 0.5d | ★ |
| K 流距/标题下距 | 高(全文页节奏) | 0.5d | ★ |
| M 案1 首屏陈述 | 高(第一屏人格) | 0.5d | ★ |
| P 代码块窗口化 | 高(技术轨视觉主件) | 1d | ★(成本略高但收益覆盖全部技术文) |
| Q 纸面板+金句 | 中高 | 0.5d | 次批 |
| O 微交互 token | 中(一致性负债清偿) | 0.5d | 次批 |
| N 图库质感 | 中 | 1d | 次批(含⚠两案) |
| S 热力图 | 低(大概率维持现状) | 0.2d | 随批 |
**前 5(高收益低成本)**:L → R → K → M案1 → P。合计 ≈3d,其中 L/R/K 纯 global+tokens 层,一次提交可收。
## 4. 明确不做(与灰阶克制红线冲突,含理由)
1. **玻璃拟态/大面积毛玻璃**:backdrop-filter 大面积使用与"纸墨实体感"冲突;微信内置浏览器兼容与滚动性能翻车史;Header 8px blur 轻量例外保留。
2. **渐变色文字/渐变大块**:全站唯一强调色(--accent 单色)是丙路线根基;渐变=多色并存,01 报告诊断的多色病复发。
3. **大圆角卡片风(≥16px)**:圆阶上限钉 `--radius-l:14px`;大圆角是消费 App 友好风,与终端/制版感相反。
4. **macOS 三彩圆点/彩色窗条**:代码窗条采灰阶三档(P 卡);彩点是全站唯一彩点的地位争夺者。
5. **噪点/纸纹覆盖层**(02 报告 Tier1 曾列,本批否决):纸感已由 `--paper` 米白承担;噪点在低分屏/微信内染摩尔纹,reduced-motion 需额外豁免,收益/成本比不成立。
6. **表格 Zebra 斑马纹**:隔行灰块密度过高,与分隔线骨感二选一取线(R 卡)。
7. **代码行号**:内容以短命令块为主,行号吃掉 320px 移动端宽度;Shiki attrs 可后补不锁死。
8. **行尾点号悬挂/首行缩进**:03 报告已证伪(无出版惯例/避头尾风险)。
9. **弹跳缓动/大面积视差/入场加码**:红线"不弹跳宁轻勿闹";现有 12px rise-in + 1px hover 是上限。
10. **自定义光标**:02 Tier3 已判,正文必须标准 I-beam。
## 5. 截图问题清单(⚠视觉待验——交视觉模型,附证据文件)
| # | 问题 | 证据对 |
|---|---|---|
| 1 | 首屏 M 案裁定:现状 IdCard+列表直连的密度 vs mockup hero 的呼吸,哪个更"被设计过"?案2 hero 是否过度? | home-{light,dark}.png ↔ mock-home-{light,dark}.png |
| 2 | 纸面板 Q-A/B:通栏 hairline(现状)vs 全边框圆角卡(mockup),哪个更"书页"?暗色下 paper #f8f6f1↔#201d18 转换是否自然? | reading-{light,dark}.png ↔ mock-reading-{light,dark}.png |
| 3 | 代码块 P:加灰阶窗条+语言标签后是否加分?(可先看 mockup term 窗对比现裸块) | tech-{light,dark}.png ↔ mock-tech-{light,dark}.png |
| 4 | 图库 N:stage 米灰衬底 vs 直贴,哪个衬托照片更好? | gallery-{light,dark}.png ↔ mock-gallery-{light,dark}.png |
| 5 | 热力图 S:灰四档 vs 绿四档的量级辨识与首页色彩重心 | home-{light,dark}.png(热力图区) |
| 6 | 页面标题降档(27→22px):books/gallery/moments 三页标题现值是否过重? | books-{light,dark}.png(无 mock 对照,独立判断) |
| 7 | 现状整体灰阶层级是否"够用"(rauno 12 档 vs 我们 5 档):列表行 hairline+日期档位是否单薄? | home-*.png 列表区 ↔ mock-home-*.png |
## 附:测试床与复现
- 截图环境:`npm run build`(34 页)→ `python3 scripts/build-perf/gz-server.py 18800 dist`(写稿时仍在跑,用后可杀:`pgrep -f gz-server` 取 PID kill);脚本 `/tmp/beauty-shots/shoot.cjs` 与 `shoot-mockup.cjs`(`NODE_PATH=$(pwd)/node_modules node …`)。
- 对比度计算:sRGB 相对亮度公式手算(§1-4 数值即此口径),可直接进验收注释。