Article cover

博客模板更新史 · 希尔维特卷其二 · 第四章

非常舒服的春天来了,晚上八点多,天还透亮着,每天像是凭空多出来一个多小时的日光,睡觉时间就这么被压缩了,开心得要死,但也觉得有点睡眠不足,有些疲劳。

自从上次更新博客系统依赖,我陆陆续续又做了一大堆更新,一直到昨天为止,一批新的内容组织架构基本已经全都完成,是时候再写一篇博客更新日志了,于是就有了本文。这篇里面会同时包含一些内容思考、设计想法和技术细节,希望你能喜欢。

对了,我不是那种只折腾模板不写内容的博主喔,今年一年已经输出了十四篇长篇正文、十二篇短篇笔记,合计二十六篇,不说是独立博客更新频率顶标,也有一个胸部水平了 c⌒っ.ω.)っ

那么,欢迎来到胸部?

内容架构更新

笔记区

内容方面最大的变化是加了一个「笔记区」,内容介于正式文章与一句话碎片之间,专门容纳那些难登大雅之堂的小文字。我的博客上还有一个叫「To→Witter」的栏目,用来存放一些灵感火花,可能攒着攒着就会憋出来正文。你可能会觉得很怪,新区域为什么会有好几年前的文章?这是因为我把自己 Telegram 频道里面有点篇幅的东西也都收拾到这个区域里了。毕竟频道里我整天高频碎碎念,有价值的东西还是应该拎出来放到一个好检索的地方。

最近一个月开始,笔记区的内容边界有点模糊。有舰长问我,大语言模型用于写作这件事,最近有没有新的趋势。一年前我写过一篇相关的文章,但各种新模型和产品出现之后,当初的实践方式已经有些失准。我答应了重新写一篇。像这样的篇幅不算小,却又不适合放在主信息流里,于是就留在了笔记区。我真的很不想把这种杂文推到你的 RSS 里。

同样的逻辑,我在笔记区里写了六篇统计学教程。这些东西写得很快,但我不觉得关注我博客的人会想看统计学教程,不过它们又确实重要。所以我把它们藏在笔记区,准备攒到十篇后搓成一个大集合,再发一篇主导读文章。

还有一些生活琐事,以及与大语言模型探讨时留下的好玩聊天记录,也被我收拾到了这个区里。

正因为定位犹如杂物间,设计上做得也就比较简单,没有题头图,没有标签系统,只保留了分类系统(不同分类上方有一颗胶囊样式的标识),一切服务于我能快速噼里啪啦打篇东西出来。这个区域的正文字体相对大一些,内容少,但版式要撑开。

特刊系统

另一个大动作是把边栏的文章分类索引拿掉了。我观察了很久,发现几乎没有人会从那里点击阅读文章。放在那里就是一个纯粹的占位符,拿来充长度、优化 SEO 的。几乎找找不到一个理由说明读者真的需要它。

所以我手起刀落把它咔嚓掉了。替代它的是一整套特刊系统,功能上类似知乎专栏。我博客上的许多文章天然可以组成一个主题,但如果用分类去归类,会显得非常凌乱,因为读者也不知道该从哪里开始读。于是我做了新的页面:把相关文章列进一个特刊,再为每个特刊单独写一篇导读。一篇文章可以属于多个特刊,而每个特刊里的导读文字各不相同。如果你对博客的某一个面向感兴趣,想从头到尾系统地看,这个系统会告诉你怎么看、按什么顺序看、从头到尾意味着什么。

目前特刊只索引文章和笔记,但说不定以后我也会给 To→Witter 做拓展,并且让特刊能够列出脑袋里面蹦出来的随机想法。

左面是旧版本的分类列表,右面是特刊列表,后者看上去更诱人一些。
左面是旧版本的分类列表,右面是特刊列表,后者看上去更诱人一些。

视觉上,我让特刊目录看起来像书店里的书架。把特刊标题用文字列表拉出来太无聊了,所以我用 GPT 给每个特刊画了一个封面,陈列在边栏上。你可以左右滑动,体验类似 Apple BooksGoogle Book Store

点进去后,页面设计参考了 Google Books 早期的 Material Design 风格,下半部分则混入了 Material Design 官方博客的布局样式。标题、封面、导读,呈现得像一本书的介绍页。我一度想在介绍页里放一个「一键下单」按钮,按下去跳到捐款链接,最后还是矜持了一下。

人工智能特刊的内容介绍
人工智能特刊的内容介绍

关于创作者与读者的距离

这里稍微岔开一笔。这两年我在文字创作上的投入比以往大很多,内容质量也高了不少。如果让我全职天天写,我大概也是可以做到的。那么搞知识星球、私域流量那一套,是不是也可以呢?大概吧。不过我很不喜欢某些人把博客文章全部锁起来、不付费就不能看的做法。在我力所能及的范围内,我希望自己产出的知识尽可能开放,让所有人都可以自由获取。

另一方面,我认为独立创作者需要保持台上台下的距离感。在创作层面,规避读者过多干涉。独立指独立地表达自己的所思所想,不以过分谄媚的姿态迎合别人。一旦有了过多「迎合」的念头,创作者的某些特质就会流失。当然,这其中有一个程度问题。完全不理会读者,看起来很讨厌;被读者声音裹挟,也相当可怕。有一天如果老读者搞出绝杀式的情绪勒索:「说你变了,我很失望,我不再给你钱了」,那对我来讲会是一件非常心痛的事。这种事情一旦多起来,创作就会被绑架。

我还是希望尽可能的 be my self,且来去自由的空间交给读者。基于这样的理念,捐款链接这次没有发生变化,依然被小心地藏在右下角,安安静静地当一个可爱的小猪存钱罐。

基本逻辑是,你都想订阅了,为什么不顺便捐一笔呢(不是——
基本逻辑是,你都想订阅了,为什么不顺便捐一笔呢(不是——

设计

卡片光影与万花筒实验

特刊页面的视觉重点是一排大砖块卡片,排成两列,每一张卡片下方有微弱的色彩光影自下而上浮现。鼠标滑上去时,光会瞬间铺满整张卡片,缓慢流动的光线在背景上移动。前景文字和背景之间不是简单的覆盖关系,它们之间的颜色会互相匀染,更鲜艳的颜色能照出更亮的文字,让文本展现出一种被光打透的质感。每一张卡片的色彩都略有不同,整体视觉呈现出有生机的、宁静的流动感。

亮起和没有亮起的卡片。
亮起和没有亮起的卡片。

这个效果的原理来自我之前做失败的一款产品,但有了锤子自然会四处找钉子,总算找到了个地方把这个动效用了起来,好开心。

本来博客的题头图就是一张 1900×500 的长条图。我把它切成五等份,摆进一个方形的万花筒里,五个扇形格子各放一份,让它们在其中正向旋转。这里有一点很 Tricky,如果每个格子都正向旋转,即使加上模糊,整张图看起来仍然在朝某个方向转动。于是就有了另外一层动效:让整个万花筒反向旋转,抵消掉每个格子正向旋转带来的视觉效果。再刷上一层模糊之后,就是这种不断流动的色彩与光影,有一种 Windows Vista 的质感。

三张不同的图混在一个万花筒里
混在一起就是梦幻渐变光效了

图片的色彩调整也有说道,因为很多图片的对比度和明度过高或过低,不适合前景与背景互相映衬的设计。方案是在 OKLCH 色彩空间下做调色,对明度和饱和度过高或过低的颜色进行线性压缩,输出一批烘焙图。

最初本来图省事,直接在客户端计算,后来发现大量图片加载时风扇狂转,显然行不通。于是写了个脚本,烘焙成尺寸极小、色彩专门为此场景调校过的图,灌进万花筒,效果很好。

以及一个小细节,这个卡片已经有触屏按下动效了(色彩充满卡片),因此 Chromium 系浏览器添加的「蓝色遮罩层」就有点多余。我加了一行比较罕见的 CSS 把它给去了,可喜可贺。

阴影系统的贝塞尔曲线重制

全站范围做了一项重要的视觉修正:基于多边形拟合的阴影系统。

原本文章题头图上方就铺了一层渐变色,用于把文字从背景中拖出来。但以前的版本用的是一般的线性渐变。其实大多数情况下都没啥问题,但在从实色到全透明的过渡中,CSS 的标准处理方式会产生一条明显发亮的边界。不是说数学上引擎算得不对,这是心理物理学层面的问题,你的脑子就是能补出一个根本看不见的硬边,非常难看。

上图为修改前,下图为修改后
上图为修改前,下图为修改后

我一度以为是色彩空间设置或颜色选择的问题,花了很长时间排查,结论是认知层面的问题。某天突然想起 Material Design 的阴影系统, Material Design 的卡片阴影有很清晰的物理直觉,它用了多个不同浓淡、不同半径的阴影叠加,用以拟合自然界的光影曲线。CSS 的 box-shadow 不允许直接套用复杂的光影公式,所以 Material Design 的实现选择了一条等效路径,用多个阴影层去逼近效果。

Material Design 的柔和阴影,图片来自 Material Design 官网
Material Design 的柔和阴影,图片来自 Material Design 官网

我之前狠狠地玩过这个阴影系统,通过线回归方程拟合出适用于任意深度的阴影公式,这样可以得出非整数,甚至超出原本设计系统参数的视觉效果。现在我的博客仍然在用这套东西。基于这段经历,一日我突发灵感,既然阴影可以用多边形拟合,那么渐变或许也可以。搜索之后发现,这确实是 Web 设计领域一个被反复讨论的问题。甚至有人提出了解决方法,做了插件,提了 CSS 标准草案,但可惜现阶段还不能直接用(草案过了你也得等 Safari 实现,Safari 实现了你也得等五六年,让旧版本系统被自然淘汰)。

好在有现成的工具能用,随手生成了质量更高的阴影叠加层,替换掉了之前很丑的渐变版本。现在特刊页面的光影、搜索页面背景的光效渐变,全部使用了贝塞尔曲线多边形拟合出来的阴影。

这是一个值得所有 Web 开发者认真学习的设计实践。

全文搜索

这次还加入了正儿八经的全文搜索功能。以前是用 DuckDuckGo,输入关键词后直接跳转到外部搜索页面,但总觉得跳出去这事情不够优雅,显得博客完成度不高。所以这次引入了一个现成 Pagefind,它会在构建时扫描所有输出的 HTML,进行分词并生成数据库。你可以选择什么时候加载 pagefind 本身,什么时候加载数据库。我的设计是用户点击搜索之后才会加载这个数据库,对网站性能的影响相对可控,搜索的准确度也有提升。

界面设计上做了一些巧思。搜索结果以卡片形式展示,每次数据变化时都有动画过渡。正在搜索时,搜索栏背景上会出现一层隐隐的光效。搜索栏本身是 sticky 的,向下滚动时依然可见,可以随时修改检索关键词。因为两层卡片叠在一起很丑陋,所以在非 Sticky 的状态下把背景变成了渐进式渐变,背后的搜索状态光效也跟着做了一点微调。

搜索状态指示
搜索状态指示
渐进式模糊滤镜
渐进式模糊滤镜

性能

首先,最大的性能更新是我把博客系统的缩进统一改成三空格缩进了,可以时刻让大脑发光,对低血压友好!

PageSpeed Insights 指标

众所周知地,本博客在移动端的 Lighthouse 指标一直没做到四绿,只有桌面端是四绿的。加之本博客托管在 Netlify 上,尽管可以保证中国大陆的正常访问,但是 TTFB 相当不理想,但找不到更好的免费静态 CDN 方案,只能大致维持现状。Google 的遥测捕捉到的结果真的很烂。为了让指标有一丝丝好看(因为 Google 的搜索排名会参考这些指标),瞧瞧剩下可以优化的小可爱,就只有 FCP、LCP 了。但说实话,TTFB 那么大的情况下 FCP 和LCP 不可能好看……

移动端四绿,这是最难做的
移动端四绿,这是最难做的

哦,对了,FCP 基本上是第一个可见元素刷出来的速度,LCP 是最大视觉元素刷出来的速度。

整个优化过程有一种破解 Google 评分规则的赶脚。但 Google 自己的网站其实也过不了自己设定的「四绿」标准,特别是那个 Performance Metric。一些推荐规则也很反直觉:比如在 HTTP/2 下,按道理把 CSS 拆成更小的碎片并行加载效率更高,但 Google 的度量工具不认,它要求你合并成一个大 CSS 文件,否则就判定有太多东西阻塞了网络请求。为了迎合它的建议我甚至把一些小 CSS 直接塞到了 HTML 里绕开了单独的网络请求。实际上这很不利于优化,但它既然都要了,咱也不能不给是吧……

How……

题头图加载优化

题头图是一张非常大的图片,在移动端第一屏它几乎占据全部视觉空间,所以这块的加载速度直接影响 LCP 指标。最初的思路是用 Blurhash 先展示一个哈希生成的模糊占位图,等图片加载完成后再切换。但 Blurhash 依赖于 JavaScript 运行,因此你得等 JS 加载,再等 Svelte 水合完毕,占位图才能显示出来,在时间线上非常靠后。

所以要做的第一件事就是 Blurhash 提前渲染成一张图片嵌入 HTML。虽然渲染成 PNG 是 K 级别,但渲染成 WebP 编码后能压缩到 B 级别,内容长度并不比纯 Blurhash 字符串长多少。所以你甚至可以直接把这张 WebP 编码成 base64,嵌入到 hero 图的组件里,省去了一次额外的网络请求。

(侧面烘托出了把 Blurhash 渲染成超长 CSS 很蠢的氛围……)

但这只解决了一部分问题。Blurhash 生成的是模糊的低信息量图像,Google 的指标计算以图片实际显示尺寸为分母、图片信息量为分子,信息量不够的图片不会被计入 LCP。这只能解决 FCP。这意味着你辛苦加载的模糊占位图,在指标层面等于不存在,LCP 仍然要等原图加载完才开始计算,惩罚依旧。

解决方案是绕过整个 Svelte 引擎:在 img 元素里静态地写一段回调,图片下载完成后直接切换 CSS 类。这样图像预载和 Svelte 的水合流程彻底脱钩,图片只要下载完毕就能自动切换。代价是必须手写 HTML,Svelte 5 的引擎不允许这种做法,事实上也确实不应该这么做。不过但分数确实上去了,事情真的很扭曲……

看到这段代码我真的很想吐……
看到这段代码我真的很想吐……

以及,为了省一个网络请求,题头图的 SVG 直接嵌入 HTML 了,这样 HTML 加载完那 Logo 立刻就能显示出来,对 FCP 有好处……

图像素材优化

题头图原本是高压缩的 JPEG,还不小心把原稿搞丢了。把 JPEG 转成 WebP 后,尺寸更小、效果更好,但会涉及二次压缩的问题,原本已经被压得相当难看的图需要修复。所以这次把显卡用了起来,找了一个表现不错的 ComfyUI 插件,几款工具组合在一起,把图片的渐变部分修好,重新贴回原图,再转成 WebP,最终少了几百 KB,可喜可贺。

所有题头图也做了多尺寸烘焙,通过 srcset 为移动端用户提供更小的图片版本,省一点流量。在 Google 的建议下这样调整,加起来可能也就省了不到 200KB,但还是做了。

折腾完这一轮,本地 Lighthouse 桌面端是 97,移动端也到了 97。Accessibility 两端都是 96,Best Practice 100,SEO 100。在线版仍然不及格,TTFB 这事情确实救不了……

此刻我的心情 be like
此刻我的心情 be like

而且有些地方感觉自己就是在强行 Hack Google 的那套算法让它不要给我打低分……虽然一顿操作猛如虎网站确实是快了一些,但很多地方改得很没道理……

关于设计

所有的优化都没有牺牲视觉品质。博客的视觉层次依然是丰富的,有光影流动的卡片,有色彩各异的题头图,有良好的信息层级。在这个基础之下,可本站仍然在桌面端和移动端都做到了四绿。这足以说明,追求性能并不需要把网站做成「丧葬系」。纯黑纯白、再加一点用错的阴影。我之前在另一篇文章里已经批评过这种做法:暗色背景下叠亮色阴影,丑陋到让人睡不着觉的地步。很多博客为了追求四绿,把页面搞得没有一点颜色,没有一点图片,没有一点质感,仅仅为了少写几行 CSS,甚至有乐于极端优化的开发者刻意做 No JS,把视觉设计的品质牺牲殆尽,然后再冠上「极简」的帽子。

我觉得不咋行……当然你开心就好……

简洁的设计不意味着一马平川什么也没有,字体选择、色彩选择、设计元素的堆叠方式、内容铺陈的节奏、信息的层级结构、视觉的引导,这些设计要素必须被认真思考,逐年累月的思考。把这些全都省略掉,说自己是「极简」,然后标榜「四绿」,是一种设计上的怠惰,敝人难以认同。

尾巴

仔细看的话,这个博客现在看起有点信息门户的味道了,专栏特刊承担导读功能,笔记区收容短篇和碎片,To→Witter 捕捉一闪而过的念头。年初写了大量文章,更新频率也变得很高。更高频率的更新或许会产生更多的社区回响,但对我而言,它始终只是我在互联网上的一个小房间。就像从前在北京折腾小房间一样,今天加一点东西,明天加一点东西,慢慢就变成了一个住在里面很舒服的地方。

哪怕是我博客的老读者,只要我不说,估计也不太会会发现这次更新的功能。大的信息框架几乎没变,不过细节的积累让整体体验变得细腻了不少。借着这次行文,我翻到几年前的博客截图,那时的设计虽然规整,但的确是少了一点视觉上的丰富度,少了一点信息的层次。经过一轮轮迭代,它越来越接近我想要的样子。

这件事让我非常开心。

喜欢~

Comments

Loading animation

Loading comments...