简介:一套以中华历史为主题的HTML5+CSS3+JavaScript多页面网页设计成品,共10个独立页面,适合大学生完成Web前端期末作业、课程设计或毕设参考,也方便前端初学者通过完整项目学习网页制作流程。压缩包7.33MB,共86个文件,包含10个HTML页面、5个CSS样式文件、5个JS交互脚本,以及大量jpg/png历史图片素材和1个PSD源文件,目录按功能划分,结构清晰,易于查看页面、样式与脚本的关联,浏览器打开即可直接运行。内容覆盖中华历史中的主要时期、历史人物与名著故事模块,配有图片轮播、动态导航、人物介绍等常见交互效果,整体风格统一,视觉元素丰富。已有437人学习/浏览,完整度和实用性获得认可。对于需要快速完成文化历史类网页作业的同学,这套源码提供了从页面布局、视觉风格到交互逻辑的完整参考,可在其基础上修改扩展,帮助加深对HTML语义化、CSS布局与JavaScript事件处理的理解。
1. 从期末作业到能公开展示的“中华历史”专题站:为什么 10 个静态页面比堆特效更值钱
老师把题目定为《文化历史·中华历史 10 个页面》时,很多同学的第一反应是:10 个页面要写 10 个 HTML?其实最纠结的不是数量,而是 10 个页面如何长得像同一个网站:同一套导航、同一套卡片风格、同一套强调色,演示时还能讲清楚为什么这么拆。在 Web 前端期末作业里,得分点从来不是 JavaScript 特效密度,而是信息架构与可维护性。先定 10 个页面各放什么历史内容,再搭“一个 HTML 骨架 + 一套 CSS 变量 + 一个全局 JS”,大约能省出两天时间,评审翻页时也会看到明显的工程意识。
2. “10 个页面”的信息架构:先用一张表定目录,再搭 HTML5 骨架
网页设计最容易翻车的场景不是某个页面没做出来,而是 10 个页面做完后,6 号页面和 3 号页面长得像两个网站。原因是做到第三页时临时加了一套局部样式,到第六页又补了一段覆盖,最后 CSS 叠到一千多行,改一个标题颜色要翻半天。所以动手写 index.html 之前,我一般先把 10 个文件画成一张站点地图:文件是什么、导航怎么连、图片素材放哪个目录,全部落在纸上。
2.1 为什么先把 10 个文件画成一张站点地图,而不是直接写 index.html
考试时间有限,推荐把 10 个页面按主题排成一条线:一个总览页、七个历史时代页、一个文物图册页、一个参考资料页。每个页面只负责一个主主题,页面之间用统一导航串联,评审从任何一页都能点回首页。这样安排还有个实际好处:历史大事、文物图片、术语注释可以集中整理成一张素材表,写页面时不需要在 10 个文件之间来回猜内容。
文件名按“语义化 + 拼音缩写”命名,例如prehistory.html、qin-han.html、tang.html。文件名只用小写英文字母与连字符,不要用汉字文件名,也不要叫page1.html到page10.html——10 个文件之间要互相引用,可读的文件名能直接在浏览器地址栏看出你讲的是哪个时代。
2.2 中华历史专题的 10 个页面与作业评分点对照表
这份清单不是作文大纲,而是文件清单、导航清单和图片清单。每页对应一个可以演示的前端特性,保证 10 个页面里至少出现 7 种不同交互,评委点开任何一页都有东西可讲。
| 文件 | 页面主题 | 内容重点 | 可演示的前端特性 |
|---|---|---|---|
| index.html | 总览与时间轴 | 上古到当代的大事年表 | 锚点跳转、卡片布局 |
| prehistory.html | 上古与考古 | 良渚、三星堆、甲骨起源 | 图片灯箱、两行文字打点 |
| xia-shang.html | 夏商周 | 青铜器、甲骨文 | 时间轴、段落装饰分隔线 |
| qin-han.html | 秦汉 | 长城、汉简、丝路沿线文物 | 数字滚动、地图示意 |
| tang.html | 大唐风华 | 唐诗、大雁塔、唐三彩 | 手风琴、引用排版 |
| song.html | 宋代市井 | 交子、瓷器、勾栏文化 | 关键词筛选、实时搜索 |
| yuan-ming.html | 元明 | 杂剧、宝船、造船工艺 | 卡片翻转、字体渐变标题 |
| qing.html | 清代营造 | 故宫琉璃、木作结构 | 图片左右对比 |
| modern.html | 当代中国成就 | 高铁、航天、生态保护 | 数字滚动、滚动入场动画 |
| about.html | 参考与版权 | 图片来源、制作说明 | 列表、页脚注释 |
表格里的“演示特性”不是每个页面都要做,而是保证 10 个页面里至少出现 7 种。期末评分通常看“丰富度 + 完成度”,与其塞 10 种没调完的效果,不如把 7 种全部调试到不报错。时间不够时,优先保导航、灯箱、筛选这三样,因为演示时最容易被人点到。
2.3 一个能复制 10 次的 HTML5 骨架
以下骨架是 10 个页面共用的模板。复制到新文件后只改title、body类名、h1和导航里的“当前页”标记,其余结构保持不变。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>夏商周 · 中华历史专题</title> <link rel="stylesheet" href="css/style.css"> <script src="js/app.js" defer></script> </head> <body class="page-xia-shang"> <header class="site-header"> <a class="brand" href="index.html">中华历史</a> <nav class="main-nav" aria-label="站点导航"> <a href="index.html">首页</a> <a href="prehistory.html">上古</a> <a href="xia-shang.html" aria-current="page">夏商周</a> <!-- 其他时代页面按顺序继续添加 --> </nav> </header> <main> <article class="hero"> <h1>青铜与甲骨:夏商周</h1> <p class="hero-lead">这里是页面导语,一句话点明本页主题。</p> </article> <section class="card-list">:root { --clr-bg: #f7f3e8; --clr-panel: #ffffff; --clr-text: #2b2b2b; --clr-accent: #8a1f1f; --space-section: clamp(3rem, 6vw, 5rem); --radius-card: 12px; --shadow-card: 0 6px 18px rgba(0, 0, 0, 0.08); } body { margin: 0; background: var(--clr-bg); color: var(--clr-text); font-family: system-ui, "PingFang SC", "Microsoft YaHei", sans-serif; } h1, h2, blockquote { font-family: var(--font-serif); } .card { background: var(--clr-panel); border-radius: var(--radius-card); box-shadow: var(--shadow-card); padding: 1rem; } /* 页面层覆盖:唐代页面把强调色调成琥珀色 */ body.page-tang { --clr-accent: #9b5e2e; }逻辑说明:页面差异被收敛到body.page-tang这个类名里。唐代页面只需要重新定义--clr-accent,.card、按钮、链接这些基础组件会自动跟着变色,不需要在page-tang里再写一遍组件样式。评审老师翻代码时一眼就能看出结构:全局一份、页面一份。如果某个页面需要完全不同的背景图,也放在body.page-tang里覆盖background-image,不至于污染全局规则。
3.3 高频细节实测:垂直居中、打点省略、删除线与段落分隔线
网页设计作业里被问最多的几个 CSS 问题,其实都是固定套路。输入框和按钮在卡片里垂直居中,给父容器加display: flex; align-items: center; gap: 0.5rem,比反复试margin-top可靠;卡片标题超出一行会溢出,用单行打点省略;两行超出则用-webkit-line-clamp: 2;历史专题里常有“某展览已结束”的提示,给日期加删除线比标红字更克制。
/* 输入框与按钮一行垂直居中 */ .field-row { display: flex; align-items: center; gap: 0.5rem; } /* 单行打点省略 */ .ellipsis { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } /* 两行超出打点 */ .multiline-ellipsis { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } /* 已结束状态:用删除线标记日期 */ .closed-date { text-decoration: line-through; color: #888; } /* 段落之间的装饰分隔线 */ .article-divider { height: 1px; background: linear-gradient(to right, transparent, var(--clr-accent), transparent); }参数说明:text-overflow: ellipsis必须配合overflow: hidden和white-space: nowrap才生效,少一个都不行;-webkit-line-clamp是两行打点的主流方案,但需要保留display: -webkit-box和-webkit-box-orient: vertical,现代 Chrome 和 Edge 都支持。.article-divider用渐变色做水平分隔线,两头透明中间强调色,是历史类页面最常用的排版手法。
提示:CSS 删除线是
text-decoration: line-through,它会贯穿整段文字。如果只想划掉日期而不是划掉“日”字,把日期包在<span class="closed-date">2025-01-01</span>里,不要给整张卡片加删除线。
4. 让中华历史页面“会动”的最小 JavaScript 方案
期末作业里见过不少人从网上下载 800 行动效塞进页面,结果答辩时还没讲完就报错。与其这样,不如围绕内容挑三个每页都能用的交互:导航吸顶、文物图片灯箱、朝代关键词筛选。三者都建立在语义化 HTML 上,代码量不大,却能让评委连续看到三个不同的响应效果。
4.1 三个交互就够期末演示:导航吸顶、图片灯箱、关键词筛选
| 交互 | 推荐触发方式 | 说明 |
|---|---|---|
| 导航吸顶 | scroll事件切换 class | 配合 CSSposition: sticky,减少 JS 计算 |
| 图片灯箱 | click事件读取 dataset | 不引入任何外部库 |
| 朝代筛选 | input事件 +String.includes | 大小写不敏感,匹配卡片文本 |
下面按顺序给出能直接放进js/app.js的代码。注意三个功能相互独立,删掉某一个不会影响另外两个。
4.1.1 原生 JS 实现导航吸顶
导航吸顶有两种做法:纯 CSSposition: sticky,或者 JS 监听滚动后加类名。推荐后者,因为吸顶时还能顺带加深阴影、改变导航底色。
const header = document.querySelector('.site-header'); function onScroll() { header.classList.toggle('is-sticky', window.scrollY > 70); } window.addEventListener('scroll', onScroll, { passive: true });配套的 CSS 写在style.css里:
.site-header.is-sticky { position: sticky; top: 0; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08); }参数说明:window.scrollY > 70意思是页面往下滚超过 70 像素才触发吸顶,避免刚打开页面导航就贴边。{ passive: true }告诉浏览器这个监听器不会调用preventDefault,滚动时浏览器不用等 JS 执行完再渲染,长页面滚起来更顺。如果你希望导航一直吸顶,直接把position: sticky写在.site-header上就行,JS 这段可以完全去掉。
4.1.2 原生图片灯箱
文物页面通常配大量器皿照片,小图预览、点击看大图是刚需。外面有很多灯箱插件,但原生写法只有十几行,期末作业里更好交代。
// 在页面底部创建一个全屏遮罩层 const lightbox = document.createElement('div'); lightbox.className = 'lightbox'; document.body.appendChild(lightbox); // 所有带>.lightbox { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.75); z-index: 999; } .lightbox.is-open { display: flex; align-items: center; justify-content: center; } .lightbox img { max-width: 90vw; max-height: 85vh; border-radius: 8px; }参数说明:缩略图在小图src之外加一个>const filterBox = document.querySelector('[data-filter]'); const list = document.querySelector('[data-period-list]'); filterBox.addEventListener('input', (event) => { const keyword = event.target.value.trim(); list.querySelectorAll('.card').forEach((card) => { const text = card.textContent.toLowerCase(); const hide = !text.includes(keyword.toLowerCase()); card.classList.toggle('is-hidden', hide); }); });
配套 CSS:
.card.is-hidden { display: none; }逻辑说明:event.target.value.trim()去掉首尾空格,避免用户只敲空格时把所有卡片藏起来。card.textContent是卡片内所有文字,不需要为每张卡片额外维护关键词字段;如果你只想匹配标题,把textContent换成card.querySelector('h3').textContent即可。toLowerCase()让英文也能忽略大小写匹配。is-hidden这个类名语义清晰,比直接改style.display = 'none'好排查,因为以后若要做“无结果提示”,只需要再写一条.card-list:has(.card:not(.is-hidden))之类的规则。
如果 10 个页面共用一组朝代按钮,而不是单个输入框,事件委托是更优解。把监听绑在按钮组的父容器上,通过closest找到被点的按钮:
document.querySelector('.filter-buttons').addEventListener('click', (e) => { const btn = e.target.closest('[data-filter-btn]'); if (!btn) return; const period = btn.dataset.filterBtn; list.querySelectorAll('.card').forEach((card) => { const isMatch = period === 'all' || card.dataset.period === period; card.classList.toggle('is-hidden', !isMatch); }); });closest('[data-filter-btn]')会从被点击元素向上找最近的按钮,即使你点的是按钮里的<span>也能正确识别。dataset.filterBtn对应 HTML 里的>.card { transition: transform 0.25s ease, box-shadow 0.25s ease; } .card:hover { transform: translateY(-4px); box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12); }
为什么不用 JS 写mouseenter?因为 CSS 在事件触发和样式计算上更直接,滚动时也不会产生额外监听器。JS 只在两种场合介入:一是进入页面后需要延迟动画,二是滚动到某个位置才播放。
滚动入场动画用IntersectionObserver最省资源:
const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { entry.target.classList.toggle('is-visible', entry.isIntersecting); }); }, { threshold: 0.15 }); document.querySelectorAll('.reveal').forEach((el) => observer.observe(el));.reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.6s, transform 0.6s; } .reveal.is-visible { opacity: 1; transform: none; }参数说明:threshold: 0.15表示元素至少 15% 进入视口才触发动画。滑块往下滚到有reveal的元素时,元素从半透明下方位移进入;当元素滚出视口,is-visible会被移除,再次滚回来动画会重播。这个效果很适合放在每个朝代页的文物卡片区,演示时评委自然往下滚,不用你主动操作。
5. 上交前跑一遍这 5 个检查,再补一个加分交互
10 个页面全部写完,验收比写新页面更关键。以下检查项按碰到频率排序,每一项都可能让作业在演示时当场出问题。
5.1 最常让期末作业“降级”的 3 个编码雷区
第一,路径问题。index.html里用href="css/style.css"是相对路径,本地双击打开不会出错;不要写以/开头的绝对路径,也不要写C:\用户\...这样的本机路径,换一台电脑演示就全部失效。第二,缓存问题。改完 CSS 页面没变化,先按Ctrl+F5强制刷新;如果还不行,检查<link>标签里的href是不是拼错。第三,编码问题。所有 HTML 文件在<head>最前面写<meta charset="UTF-8">;JS 文件里如果有中文字符串,保存时也选 UTF-8,否则筛选功能会匹配不到中文字符。
5.2 用原生懒加载把 10 个页面的图片请求压下来
文物页面图片多,纯前端作业没有后端接口,首屏加载全靠浏览器自己排队。现代浏览器直接支持loading="lazy",加上后,图片会滚到视口附近才开始下载:
<img src="images/jiagu.jpg" alt="甲骨文拓片" loading="lazy" width="800" height="500">width和height要写实际尺寸,浏览器能在图片加载前预留占位,避免图片到达时下方文字整块跳动。这个属性对演示体验提升明显:打开页面前几秒只需要下载首屏可见的几张图,后续滚动时再分批加载。
5.3 键盘左右键切换朝代:10 分钟加分的原生 JS 交互
10 个页面如果按历史顺序排列,可以做一个键盘翻页的“彩蛋”:按下方向键左键回上一个朝代,右键进下一个朝代。代码放在全局js/app.js里,所有页面自动生效。
const pages = [ 'index.html', 'prehistory.html', 'xia-shang.html', 'qin-han.html', 'tang.html', 'song.html', 'yuan-ming.html', 'qing.html', 'modern.html', 'about.html' ]; window.addEventListener('keydown', (event) => { if (event.target.matches('input, textarea, [contenteditable]')) return; const current = location.pathname.split('/').pop() || 'index.html'; const index = pages.indexOf(current); if (event.key === 'ArrowRight' && index < pages.length - 1) { location.href = pages[index + 1]; } else if (event.key === 'ArrowLeft' && index > 0) { location.href = pages[index - 1]; } });参数说明:第一行event.target.matches('input, textarea, ...')是为了避免在搜索框里删字时触发页面跳转;location.pathname.split('/').pop()取当前 URL 最后一段文件名,兼容本地file://方式打开;ArrowLeft表示往“更早的历史”翻,ArrowRight表示往“更晚”翻,符合从左到右的时间线阅读方向。箭头键的键名要用event.key而不是event.keyCode,因为37/39在部分触摸键盘上不可靠,而ArrowLeft/ArrowRight这两个字符串是规范统一值。
本文还有配套的精品资源,点击获取