有段时间,因为朋友生日赶上大家都在忙,没能凑到一块儿聚餐。我答应给他补一个“有点参与感”的祝福,想来想去,与其发一条复制粘贴的贺词,不如做一个打开就能看到氛围、还能顺手点点烟花的小页面。
于是这个项目就在我本地诞生了,目录名就叫happy-birthday,页面里第一行核心标题只有四个字:生日快乐!
这是一篇完整的实操记录。我会把前后端都不依赖的静态生日祝福卡片怎么做、怎么调、怎么在手机上顺利打开分享,以及我在实际调试中踩过的坑,全部讲清楚。适合想给朋友做一张有记忆点电子贺卡的人,也适合刚接触前端、想找个轻量小项目练手的人。不需要会写后端,也不需要懂框架,会复制代码、会改文字,就能做出一个效果不差的版本。
1. 内容整体设计与思路拆解
1.1 先想清楚这张“电子贺卡”要解决什么问题
“生日快乐”四个字,做成纯文字发出去也能表达心意,所以这页面的存在理由必须是:让祝福更有仪式感、更直观、也更好分享。普通文本消息在聊天框里停留几秒就沉了,而一张打开后能看到柔和背景、动态光点、点击后放烟花的页面,起码值得朋友多看一会儿。
我更在意的是收卡人打开时的第一感受。所以页面的信息层级应该非常清楚:第一眼是“生日快乐”,第二眼是有一种“被认真对待”的视觉氛围,第三眼是可以动手玩一下的互动点,最后是落款和日期。整张卡片不用承载太多信息,多一个没用的按钮都会让体验变杂。
这个设计思路放到具体实现里,就变成了这样的结构:
- 顶部一行小字,降低开场压力,比如“送给我最重要的朋友”
- 中间主标题,用大字号和暖色突出“生日快乐!”
- 背景有缓慢漂浮的暖色光点,不干扰阅读
- 页面上只有一个核心按钮,点击后视觉上产生烟花爆散
- 底部有一行署名和日期,表示这不是网络下载的通用模板
这样用户在5秒内就能明白页面在说什么,也知道下一步可以做什么。
1.2 为什么我坚持不引入框架和动画库
如果只看“做一个带烟花的网页”,很多人会直接想到引一个Canvas动画库或者CSS特效库,但我最后选择了一个外部依赖都不用的方案。
原因很实际:静态卡片的使用寿命可能就几十次,朋友看完基本不会再访问第二遍,引入框架和动效库虽然写起来快,却会带来几个麻烦。首先是加载,移动端网络不稳定时,几十KB的文件也要多等一会儿;其次是可维护性,以后想改文案和颜色,得在一堆依赖配置里翻;最后是分享问题,把整个依赖都塞进一个文件里是最省事的,不管对方用什么设备打开,都不会因为跑某条资源失败而白屏。
所有效果只用三种基础技术:
- HTML负责语义结构,比如标题、按钮、落款;
- CSS负责排版、字体、渐变背景和柔和阴影;
- JavaScript负责Canvas背景粒子、点击爆炸和读取URL参数。
这套组合的优势是页面可以是一个独立HTML文件,用户收到后不用安装任何东西,浏览器打开就能看。如果朋友想在电脑上留档,把这个文件直接存到桌面,双击也能正常展示。
1.3 我按什么顺序安排内容区块
这个页面并不是一刀切从上往下铺内容,我是按“打开页面的一瞬间,视线应该先落在哪里”来安排区块的。
寿星打开页面的前两秒最需要被抓住,时间再久就会失去耐心。所以主标题“生日快乐!”占最大字号,也是整张卡片里视觉权重最高的部分。在这之前我放了一行很小的引语,用来柔化它的开场方式:它不是系统弹窗,也不是群发消息,而是专门做给这位朋友看的。
主标题看完,人会自然往下扫,于是我在下方放了一段祝福文案,不用长,五六行以内,因为手机屏幕本来就有限,长篇文章在阅读压力上不如短小真诚的文字。祝福文案下面才是那个互动按钮,文案用“送一份小烟花”这样具体的动作来引导操作。
最后把落款和日期放在最低处。如果对方看不到最后也没关系,前面的祝福已经完整表达了,落款只是锦上添花。
图表化的内容比一大段话更容易看清,所以我把每个区块的作用整理成这样一个表格:
| 区块 | 位置 | 作用 | 设计情绪 |
|---|---|---|---|
| 引导语 | 页面顶部 | 热身,让寿星知道这是专门给他做的 | 温柔、克制 |
| 主标题区 | 页面中间偏上 | 直接输出核心祝福 | 醒目、温暖 |
| 祝福正文 | 主标题下方 | 补充想说的话 | 真诚、口语化 |
| 互动按钮 | 正文下方 | 鼓励点按,增加参与感 | 惊喜、轻快 |
| 落款日期 | 页面底部 | 标明作者和日期,留作纪念 | 安静、简洁 |
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心细节解析与实操要点
2.1 主标题里的js_title_inner到底怎么用
画页面骨架时,我最初写的结构非常普通:
html复制<h1>生日快乐!</h1>
但实际做到一半,发现这个主标题不能只是死板的静态文本。我希望它可以根据我放到链接里的姓名参数自动变化,比如朋友收到的是xxx.html?name=阿远,打开后就能显示“阿远,生日快乐!”
要实现这种“结构固定、内容可换”的效果,就必须把变化的那部分文字单独包裹起来。我最终使用了这样一段标记:
html复制<h1 class="card-title">
<span class="js_title_inner">生日快乐</span>!
</h1>
注意这里我故意把js_title_inner作为类名,而不是给一个看起来很普通的name-text。原因有一点历史习惯:js_前缀代表这部分将来要交给JavaScript处理,我翻代码时一眼就能知道哪些地方是纯样式,哪些地方被脚本接管,不用逐行去猜。
用独立的span包住祝福词,好处非常多。如果寿星的名字很长,CSS可以单独控制这个span的font-size和white-space,不至于影响后面那个感叹号的位置。如果未来想加打字机效果,也可以只对这个span做操作,整个页面不会一起跟着动。
以后如果你还想做其他场景的卡片,比如中秋、新年,只需要保留这个替换逻辑,改掉文字内容就能复用。页面结构始终稳定,变的只是数据。
2.2 背景配色是怎么调出“暖而不俗”的感觉的
生日页面最容易翻车的就是颜色:大红大紫拼在一起,乍看热闹,时间长了眼睛累,拍照也容易过曝。我想要的是暖色调,但不是那种扑面而来的俗艳。
最终背景我选择了类似奶茶和奶油之间的组合:底部是偏暖的#fdf6ec,中部过渡到浅杏色#f9e1c4,顶部再叠一层淡金色#f7d9a1。整体就像傍晚光线打在奶油蛋糕上,亮度适中,主标题的深棕褐色#5b3a29在上面读起来也会清楚很多。
字体颜色上,我没用纯黑,纯黑在这种暖背景上会显得太重,我用了偏暖的深棕#5b4636,会更像一个整体。辅助文字则再淡一档,比如#a0826c,保证能看清又不抢主标题的注意力。
要让这个背景产生柔和层次,我用了CSS渐变:
css复制body {
background: linear-gradient(160deg, #fdf6ec 0%, #f9e1c4 50%, #f7d9a1 100%);
min-height: 100vh;
}
这里有一个细节:渐变方向我选的是160deg,不是常见的180deg。180deg是从上到下,纵深感太平;160deg加了一点点斜向角度,视觉重心会从左上走到右下,看起来像有一束光穿过整个屏幕,画面更耐看。
2.3 光点粒子的数量不是越多越好
背景里的漂浮光点,是这张页面氛围感的重要来源。数量上我做了严格限制:普通手机屏幕上同时活动的粒子最多维持在60个左右,加上点击烟花后额外出现的粒子,总量也不超过160个。
为什么不多放几百个?因为每一帧都要对这堆粒
