首页修改记录 02:把背景图变成全站氛围层
首页背景后来被抽成全站背景。关键不是复用一张图,而是把背景、遮罩、主题切换和内容可读性放到同一个边界里管理。
首页加上纽约水面背景之后,我很快意识到它不应该只属于首页。header 是全站浮动的,页面之间也应该共享同一种氛围。否则从首页点到博客或摄影时,空间感会突然断掉。
于是我把背景从首页移到了语言级 layout,变成全站统一的背景层。
为什么不放在每个页面里
如果每个页面都自己写一份背景,会出现三个问题:
- 背景图路径可能散落在多个文件里,后续不好替换。
- 明暗主题遮罩可能不一致,导致某些页面文字发灰或对比不足。
- 页面切换时背景层重复挂载,体验上容易出现闪动。
现在背景只在一个地方渲染:
// src/app/[locale]/layout.tsx
<Providers messages={messages} locale={locale}>
<GlobalBackground />
<div className="relative z-10 flex min-h-screen flex-col">
<Header />
<main>{children}</main>
<Footer />
</div>
</Providers>页面内容在 z-10,背景在 z-0。这样每个页面都能共享同一张背景和同一层遮罩。
双图而不是动态换 src
背景和 Hero 书法鸟图一样,也分成 light 和 dark 两份资源:
<Image
src={assetsConfig.hero.background.light.src}
className="absolute inset-0 h-full w-full object-cover dark:hidden"
/>
<Image
src={assetsConfig.hero.background.dark.src}
className="absolute inset-0 hidden h-full w-full object-cover dark:block"
/>这里没有用一个 Image 动态换 src。原因很简单:主题切换不应该等网络。两张图都在 DOM 里,CSS 只负责显示哪张,切换时不会出现旧图、新样式和新图加载状态混在一起的瞬间。
遮罩比图片更重要
背景图的职责是提供气氛,不是抢内容。真正决定可读性的不是图片本身,而是上面的遮罩:
<div className="absolute inset-0 bg-[var(--background)]/70 dark:bg-[var(--background)]/82" />浅色主题下遮罩稍轻,让水面和天色还能隐约出现;深色主题下遮罩更重,避免背景把正文和边框压暗。
这也是为什么最近更新、最近听歌、最近摄影这些区域仍然需要自己的内容板。背景是环境,内容板是阅读界面,两者不能互相替代。
图文并茂文章的图片怎么管理
如果以后博客需要配图,我会按图片性质分两类:
- 站点界面截图、文章插图、过程图:上传到 R2,建议未来单独用
zjBlog或zjArticles前缀。 - 极少数构成站点 UI 的固定资源:放在
public/images,例如 favicon、全站背景、Hero 图。
也就是说,普通文章配图不应该大量塞进仓库。它们更像摄影图和书法图,都是公开静态资产,适合走 R2。MDX 里可以直接引用公开 URL:
如果一篇文章需要很多图片,最好也有一份简单清单,记录原图、本地处理产物、R2 key、公开 URL 和用途。后续本地控制台就可以把这部分做成“文章图片上传”功能。
小结
背景抽成全站组件之后,页面之间的空间感更统一,代码也更干净。更重要的是,背景资源、主题切换和遮罩策略都收到了同一个边界里。
这类改动看起来只是“移动一段代码”,实际是在确定一个规则:凡是全站视觉资产,都应该由全站层管理,而不是交给某一个页面临时拥有。

