从零搭一个深空主题的 Astro 博客
三栏骨架、星野首屏、玻璃卡片——好看的不是特效,而是每一处都遵守同一套规则。
FIG. 01 / 技术
这个博客的第一版其实很丑。白底、圆角卡片、两栏布局,每个部分单看都没问题,拼在一起却像一份没写完的作业。问题不在于「不够花哨」,而在于没有一套统一的规则。
所以我推倒重来,先确定一件事:这个站应该像什么。答案是一个观测站——安静、克制、信息密度高,偶尔有一点星空的浪漫。
一、先定骨架,再定皮肤
布局决定读者第一眼的信任感。我的顺序是:先画栅格,再填内容,最后才调颜色。最终定下来的结构是「左侧身份 + 中间内容 + 右侧状态」,总宽 1720px,正文控制在 800px 以内。
三栏不是为了塞更多东西,而是让「你在看什么」和「这个人是谁」同时成立。
侧栏用 position: sticky 跟随,但只跟随一屏。超过一屏的侧栏会变成负担,读者永远看不到它的下半部分。
二、星野不是越多越好
首屏的星空用 Canvas 画,不用图片,也不用粒子库。整段代码不到 60 行,核心只有三个参数。
2.1 三个参数
- 密度:每 1.7 万像素一颗星,1440 屏大约 120 颗,再多就吵。
- 速度:透明度呼吸周期控制在 8–16 秒,快到能被察觉就失败了。
- 亮度:上限 0.73,不用纯白,避免在 OLED 屏上过曝。
// 密度、漂移、透明度区间
const DENSITY = 1 / 17000;
const DRIFT = 0.0002;
const ALPHA = [0.18, 0.73];
function draw(t) {
ctx.clearRect(0, 0, w, h);
for (const s of stars) {
const a = s.a + Math.sin(t * DRIFT + s.p) * 0.15;
ctx.beginPath();
ctx.arc(s.x, s.y, s.r, 0, 6.2832);
ctx.fillStyle = `rgba(206,233,255,${a})`;
ctx.fill();
}
requestAnimationFrame(draw);
}
流星是可选项,但频率一定要低。我把它设成 14–28 秒随机一次,超过这个频率,读者的注意力会被反复拽走。
三、颜色只要一套
深色主题最怕「五颜六色的黑」。我的做法是把颜色收敛成四个 token,其余全部由透明度推导。
| Token | 值 | 用途 |
|---|---|---|
--bg | #05070C | 页面底色 |
--surface | rgba(255,255,255,.032) | 卡片与浮层 |
--accent | #6EE7F9 | 链接、焦点、强调 |
--text | #E9EFF8 | 标题与正文 |
深色主题里不要用纯白 #FFFFFF 做正文,长时间阅读会刺眼;也不要给所有卡片都加发光,光晕一多,重点就没了。
亮色主题不是把颜色反过来,而是另起一套「黎明」色板:底色偏冷灰,强调色加深到 #0E7490,保证在浅色背景上仍有足够对比度。
四、最后
博客是长期工程,不是一次性的作品。真正决定它好不好看的,不是首屏那几秒的惊艳,而是三个月后你还愿不愿意打开编辑器,写下一段新的文字。
所以我的建议是:把复杂度花在结构上,把克制留给动效。 剩下的,交给持续写作。
评论
待配置src/consts.ts里填入 Giscus 的repo与repoId,刷新后就会显示。 仓库需要是公开的,并在 GitHub 上开启 Discussions。