模板改造个人单页网站
用途
把一份第三方网页模板 + 一堆散装素材(证件照、奖状截图、docx 文字稿、成绩单截图),在若干轮迭代内做成一份能直接双击打开、断网也能看、手机也能看的个性化单页网站。
这不是"从零写页面",而是改造:模板的版式与动效是资产,模板的外部依赖、错误文案、无关板块是负债。整个过程的主要工作量在"剥离"和"对齐",不在"重写"。
何时使用
- 用户给了
lhb.zip、模板王-xxx预览.html、或者一个下载站点的 html 包,说"按这个风格做我的/我孩子的/我学生的主页"。 - 用户给了一批奖状截图 + 一份个人介绍 docx,要求做展示页。
- 已有的个人主页需要加/改板块、修图片显示、加相册、换配色。
不适用:从零设计一套全新 UI(应直接写页面);纯静态 Markdown 报告。
四条铁律
在任何迭代中都不得违反,否则返工成本极高:
- 零外部依赖。交付物必须断网可看。禁止 CDN、
webfonts/、Google Fonts、统计脚本(hm.js)、WPS 插件、bootstrap.bundle.min.js.下载这类半截文件。图标一律内联 SVG,字体一律系统字体栈。 - 先核对素材,再动样式。图片与页面的对应关系必须用文件名 + MD5 + 图片内容三重核对。凭文件名猜内容是最常见的翻车点(把"班级团日活动照"标成"个人生活照",用户一眼就看出来)。
- 图片用
object-fit: contain,不用cover。人物照、证书、成绩单表格被裁切是用户投诉率最高的问题。cover必然裁切,contain+ 浅色底#f4f1ea才是正解。 - 每轮改动结束必须跑校验:
python scripts/validate_webpage.py <站点目录>。花括号/标签配对、JS 语法、图片引用零缺失零冗余、外部依赖清零,缺一不可。
工作流
阶段 0 · 解包与素材盘点
unzip -o 素材包.zip -d work/ # 注意:有些"压缩包"实为 docx 容器或工作区快照
python scripts/scan_material.py work/ # 列出图片(含尺寸/MD5/重复项) + 抽取 docx 纯文本
留意包里的三类东西,只有第一类要做:
| 内容 | 处理 |
|---|---|
模板 HTML + *_files/ 资源 |
改造对象 |
word/、_rels/、[Content_Types].xml、customXml/、docProps/ |
被解开的 docx 残骸 → 提取文字后不复制进交付目录 |
.workbuddy/memory/*.md |
历史工作记录,先读,可省去大量重复探索 |
word/media/imageN.png 往往就是用户素材的原图,值得逐张打开确认内容。
阶段 1 · 识别真实模板文件(最容易做错的一步)
模板站的"在线预览"页面不是模板,只是预览外壳:iframe + 百度统计 + WPS 插件样式 + demo.css。真模板在同级 _files/index.html。
判据:
- 外壳:<!-- saved from url=... -->、iframe id="preview-frame"、.wps_ai_link 样式、hm.js、路径里带"在线预览"。
- 真模板:有完整的 <body>、自己的 head(字体/CSS 变量)、正常的类名体系。
确认真实模板后,把外壳整个丢掉,从真模板的 HTML/CSS/JS 出发。若真模板文件缺失(下载不完整),按 references/03-motion-and-css.md 的动效清单凭外壳与样张反推,但要向用户说明。
细节与判据清单见 references/01-template-source.md。
阶段 2 · 剥离外部依赖
待剥离清单(逐一 grep 确认清零):
font-awesome / all.min.css / fa- / webfonts / fa-solid
googleapis / gstatic / cdn. / unpkg / jsdelivr / bootcdn
bootstrap.bundle.min.js.下载 / hm.js / 百度统计 / _hmt
wps_ai_link / preview-frame / demo.css
图标替换为标准动作:删掉图标 CSS,把每处 <i class="fa fa-angle-left"></i> 换成内联 SVG,fill/stroke 用 currentColor 继承文字色。JS 里动态拼接模板要用到的图标,抽成常量对象统一注入。
可直接取用的图标常量与注入函数见 assets/icons/icons.js。
选择器同步改名,避免"图标类名还在但样式已删"的悬空引用:
.fa-angle-left → .nav-prev、.fa-angle-right → .nav-next、画廊用 .gal-prev / .gal-next。
阶段 3 · 建立设计令牌
不要满文件替换颜色值。先在 :root 定义语义化变量,再把模板的硬编码色换成变量:
:root{
--color-txt-A2:#16324f; /* 主文字/深底 */
--color-usr-A :#a8823a; /* 强调色/金 */
--color-bg-A1 :#faf8f4; /* 页面底色/米白 */
--color-bg-B2 :#1b3b5c; /* 次级深底 */
}
配色与字体栈的选型建议见 references/03-motion-and-css.md。字体一律回退到系统中文栈(模板自带的 PoltawskiNowy/figtree ttf 通常不在包里,@font-face 会 404):
font-family: "Songti SC","Noto Serif SC",Georgia,serif; /* 标题 */
font-family: -apple-system,"PingFang SC","Microsoft YaHei",sans-serif; /* 正文 */
阶段 4 · 信息架构与素材命名
素材按用途重命名,不要留 a4ba6e76…jpg 这种哈希名——哈希名是后续所有对应的噩梦。
portrait.jpg 证件照(Hero 首帧)
life-1..n.jpg 生活照(景区/自拍/写真)
class-1.jpg 班级/活动照
volunteer-1.jpg 志愿服务照
teacher-hs.jpg 师长合影
award-*.jpg/png 荣誉证书(按事由命名:award-zhengfu / award-sanhao / award-gaokao)
cert-*.jpg 技能/结业证书
gpa-1..n.png 成绩单截图
页面骨架按下列七段组织(可按素材增删),完整建站模板与文案组织方式见 references/02-assets-and-ia.md:
- Hero(首帧证件照 + 数据三项:排名/绩点/荣誉数)
- 个人简介(叙述 + 基本信息卡)
- 能力素养(技能条 + 特性卡)
- 荣誉奖项(卡片网格 + 分类筛选 + 灯箱)
- 成长历程(时间线)
- 学业成绩 / 实践经历(截图组 + 照片栈)
- 联系与页脚
文案口径必须与用户口径一致:用户口述的绩点、排名以用户为准(截图里可能没有汇总页);修改一处就必须全局一致(Hero 数字、描述、简介、详情、板块标题、卡片共 6 处)。
阶段 5 · 保留并适配模板动效
模板值钱的地方就是动效,改造时要逐个确认存活,而不是删掉了事:
- 全屏滑动菜单(
transform:translateX(100%)+transition-delay+.loader的clip-path旋转) - 图片滑块揭幕换图(
clip-path多边形 +translateY,data-delay自动轮播,箭头 1000ms 防连点锁) - 技能条闪光(
background-position-x无限循环) - 卡片画廊(先
.deact淡出再收放父容器宽高,避免闪跳) - 内容淡入(容器加
.loaded,opacity0→1 + delay) - 时间线端点(
::before/::after圆点,或由 JS 注入节点)
改 object-fit 时注意:contain 只影响画面填充,不影响 clip-path 揭幕动画,两者可以共存。
阶段 6 · 加装通用灯箱相册
所有图片都应该可点击放大——用户对"图点不开"的容忍度为零。
使用 assets/lightbox/(lightbox.css + lightbox.js,零依赖),按 data-lb-group 分组,组内左右翻页:
<link rel="stylesheet" href="assets/lightbox/lightbox.css">
<script src="assets/icons/icons.js"></script> <!-- 可选:图标单一来源 -->
<script src="assets/lightbox/lightbox.js"></script>
<script>
ICO.hydrate(); // 把 <i data-icon="mail"> 换成内联 SVG
Lightbox.init({ sources: [
{ sel: '.projaward-card', caption: 'figcaption', group: 'awards' },
{ sel: '.g-item', caption: 'figcaption', group: 'life' }
]});
</script>
要点:
- 点击委托在
init()时挂载,脚本放<body>末尾即可 - 过滤被分类筛选隐藏的卡片(脚本内用
getBoundingClientRect()+display/visibility判定),否则翻页会翻出一堆"看不见的"图 - 说明文字优先取
<figcaption>,退回img[alt] data-full可指向原图,网格用小图、灯箱用大图- 支持 ←/→/ESC、触屏滑动、点遮罩关闭、计数器、单图时隐藏箭头、锁 body 滚动、焦点管理
接线方式与完整说明见 references/03-motion-and-css.md。
阶段 7 · 校验
python scripts/validate_webpage.py 站点目录 # 静态:配对 / 语法 / 引用 / 依赖
python scripts/validate_webpage.py 站点目录 --serve # 追加 HTTP 200 实测
校验项:CSS 花括号配对、JS 语法(node --check)、div 开闭配对、图片引用零缺失零冗余、外部依赖残留清零、HTML 引用文件存在。报告全绿才算本轮完成;"未做浏览器截图验证"要如实告知用户。
改动 lightbox.js 或 icons.js 后跑回归测试(需 npm i jsdom,用 NODE_PATH 指到 node_modules):
NODE_PATH=<node_modules路径> node scripts/smoke_test_lightbox.js
23 项断言覆盖:图标 hydrate 注入与未知名降级、灯箱收集与注入、点击打开、说明取 figcaption、隐藏项过滤、循环翻页、分组独立、ESC/←/→、点遮罩关闭。全绿即灯箱与图标逻辑无回归。
阶段 8 · 迭代
每轮迭代固定四步:
- 把用户反馈逐条列成问题清单(含用户原话),先复述再改
- 定位→修改→改完复核该问题涉及的全部出现位置(如绩点 6 处)
- 跑阶段 7 校验
- 追加工作记录到项目
.workbuddy/memory/YYYY-MM-DD.md:素材映射表、结构变更、设计决策、已知待办
素材有增删时,映射表必须写成"源文件 → 网页命名 → 内容"三列表格,这是跨轮次对齐的唯一依据。
参考文件
| 文件 | 内容 |
|---|---|
references/01-template-source.md |
模板站预览外壳判据、真实模板定位、剥离清单 |
references/02-assets-and-ia.md |
素材命名规范、图文盘点方法、七段式信息架构与文案模板 |
references/03-motion-and-css.md |
动效清单、设计令牌、字体栈、灯箱接线、高频坑位 |
references/04-case-lhb.md |
完整实战案例:5 轮迭代的全部变更与踩坑记录 |
assets/lightbox/ |
零依赖灯箱(css + js),可直接复制 |
assets/icons/icons.js |
内联 SVG 图标常量与注入函数 |
scripts/scan_material.py |
素材盘点:图片清单/尺寸/MD5/重复检测 + docx 取文本 |
scripts/validate_webpage.py |
页面校验:配对/语法/引用/外部依赖/HTTP |
scripts/smoke_test_lightbox.js |
灯箱与图标回归测试(jsdom,23 项断言) |