期末季又到了,每年这个时候私信里问得最多的就是"网页大作业到底做什么题目好""代码写完了但是看着像模板网站怎么办"。这次我就拿一个比较典型的选题来聊聊——大学生HTML期末大作业——HTML+CSS+JavaScript美食网站(西餐)。这题目看着简单,但想做得好看、功能完整、还能在答辩时说出点门道,里面有不少细节值得抠。这篇内容适合正在做前端入门大作业的同学,也适合想系统梳理静态网站开发流程的朋友参考。我会从选题规划、页面结构、样式实现、交互功能到避坑经验,完整过一遍。
1. 为什么选西餐主题:这道题的天然优势与隐藏难点
先说选题。美食类网站几乎是前端大作业的"常青树",而西餐方向又比中餐、小吃类更好出效果。原因很直接:西餐的视觉素材普遍精致,摆盘、光线、色调都比较统一,哪怕你图片是从免费图库找的,整体观感也不会太乱。另外西餐品类结构清晰,前菜、主菜、甜品、饮品天然就是一套分类体系,特别适合做导航和筛选功能的演示。
但别高兴太早,西餐网站也有隐藏难点。最明显的就是"高级感"不好拿捏——很多人做着做着就变成大红大紫的快餐店风格,跟西餐本身的气质完全脱节。西餐网站的核心调性应该是干净、留白、偏暖色调、字体有质感,所以对配色和排版的要求比一般网站高。这也是我建议选这个题的原因:它逼着你去思考设计,而不只是堆标签和样式。
再说评分维度。期末大作业通常看四件事:结构是否清晰、样式是否完整、交互是否有亮点、代码是否规范。西餐网站恰好能覆盖前三点——品类多所以页面内容丰富,风格化强所以CSS好发挥,点餐、筛选、轮播这些功能天然适合用JavaScript写。如果你还想加分,可以加一个简单的购物车或者预订表单,这在答辩时非常拉好感。
隐藏的坑也有一个:撞题率。美食网站是热门选题,你们班可能好几个组都做类似方向。所以在规划阶段就要想清楚差异化——不要用现成模板改个名字就交,而是从页面结构和交互上下功夫。比如别人只做一个首页,你把菜单详情页、预订表单、菜品筛选都做了;别人用默认字体,你引入一套好看的Web字体。差距就是这样拉开的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 开工前的完整规划:文件结构、页面清单与配色方案
磨刀不误砍柴工。我见过太多同学一上来就写代码,写到一半发现页面之间跳转混乱、CSS命名冲突、想加功能但无从下手。其实写一个静态网站花不了太久,真正耗时间的是思路不清导致的反复返工。
2.1 文件目录怎么组织
先定目录结构。标准做法是新建一个项目文件夹,里面按类型分层:
text复制西餐美食网站/
├── index.html # 首页
├── menu.html # 菜单页
├── dish.html # 菜品详情页(动态展示用)
├── reservation.html # 预订页
├── css/
│ ├── style.css # 全局公共样式
│ └── pages.css # 各页面特有样式(可拆可不拆)
├── js/
│ ├── main.js # 公共交互(导航、轮播、表单等)
│ └── menu.js # 菜单页筛选、排序逻辑
└── images/
├── hero.jpg
├── dish-1.jpg
└── ...
这里有个容易被忽视的点:图片不要散在桌面或别处,一定要放进项目文件夹。后面交作业时整个文件夹打包就行,否则图片路径一断,网页直接变"毛坯房"。
2.2 页面规划:哪些必做,哪些加分
我的建议是至少做四个页面,不多不少,正好能体现你掌握了多页面站点的规划能力:
| 页面 | 核心内容 | 必做/加分 |
|---|---|---|
| 首页 | Hero大图、品牌介绍、精选菜品展示、顾客评价 | 必做 |
| 菜单页 | 分类导航、菜品卡片网格、筛选功能 | 必做 |
| 菜品详情页 | 大图、介绍、价格、推荐搭配 | 加分 |
| 预订页 | 预订表单、表单校验、提交反馈 | 加分 |
如果你时间紧,首页和菜单页是底线,详情页和预订页看情况。但说实话,多一个详情页和表单页投入的时间成本很低(加起来可能就两小时),对整体完成度的提升却非常明显。答辩时老师问"你做了几个页面",你说四个,底气都不一样。
2.3 配色与字体:先把基调定下来
西餐网站的配色我建议用一个基础公式:暖白做底色、深灰做正文、暗绿或酒红做点缀。比如底下这套就很稳:
- 背景:#faf7f2(米白,比纯白柔和)
- 主文字:#2c2c2c(近黑色,避免纯黑的生硬)
- 辅助文字:#6b6b6b
- 强调色:#8c5b3f(浅咖)或 #6d4c41(深棕)
- 点缀色:#9a2b2b(酒红,用于按钮、价格标签)
不要用纯黑纯白和大红大绿。纯白背景配西餐图会显得很"电商模板",纯黑文字又缺少层次。米白+深棕这套组合翻车率极低。
字体方面,中文字体用系统自带的"宋体"或"微软雅黑"其实有点普通。可以考虑在页头引入Google Fonts或者免费可商用字体库,给标题用一套衬线字体,正文用无衬线字体,层次感立刻出来。不过要用的话提前确认一下网络能不能访问——做作业的机器如果环境无法访问外网字体库,页面会自动回退到默认字体,也没关系,但你要提前测一遍。
3. 核心代码实现:HTML结构、CSS布局与JavaScript交互
这里我挑几个关键模块讲,从零开始手写版。你可以直接搬,但建议读懂每一段在干什么,答辩时老师问"你这个原理是什么",你得说得出话。
3.1 导航栏:全站复用,先写结构
导航栏是每个页面都要有的,尽量一次性写好。我习惯用语义化标签 header 包裹 nav,并给当前页面对应的链接加一个 active 类名,方便高亮。
html复制<header class="site-header">
<div class="nav-wrap">
<div class="logo">La Maison</div>
<nav class="main-nav">
<ul>
<li><a href="index.html" class="active">首页</a></li>
<li><a href="menu.html">菜单</a></li>
<li><a href="reservation.html">预订</a></li>
</ul>
</nav>
</div>
</header>
这里有个小技巧:给 logo 一个英文品牌名,哪怕你本身没有真实品牌,一个好看的假名字也会让整站看起来完整度更高(比如"La Maison""Bella Vita"这类)。但别瞎编得像个真实存在的知名餐厅名,这既是礼貌也是安全考量。这个细节特别能提升整体观感。
对应的CSS:
css复制.site-header {
position: sticky;
top: 0;
z-index: 100;
background: rgba(250, 247, 242, 0.96);
backdrop-filter: blur(6px);
border-bottom: 1px solid #ebe5db;
}
.nav-wrap {
max-width: 1200px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 24px;
}
.main-nav ul {
display: flex;
gap: 32px;
list-style: none;
margin: 0;
padding: 0;
}
.main-nav a {
text-decoration: none;
color: #2c2c2c;
font-size: 15px;
letter-spacing: 0.5px;
padding: 8px 2px;
border-bottom: 2px solid transparent;
transition: border-color 0.2s;
}
.main-nav a:hover,
.main-nav a.active {
border-bottom-color: #8c5b3f;
}
注意 position: sticky 这个属性,它能让导航栏在滚动时吸在顶部,这是一个成本极低但效果很明显的交互细节。很多同学用的是别人模板里的 fixed,但 sticky 不会遮挡页面内容,更合理。
3.2 Hero区域:首屏是否吸引人,决定印象分
首屏Hero区是打分第一印象。结构上我建议放三样东西:一张高质量背景大图、一句主标题、一个引导按钮。
html复制<section class="hero">
<div class="hero-content">
<p class="hero-tag">Fine Dining Experience</p>
<h1>品味地道西餐<br>感受烹饪的艺术</h1>
<a href="menu.html" class="btn-primary">浏览菜单</a>
</div>
</section>
CSS上为了确保文字清晰,背景图可以加一层暗色遮罩。这里有个特别实用的写法:用 linear-gradient 叠加在 background-image 里,不需要额外加一个div。
css复制.hero {
min-height: 70vh;
background:
linear-gradient(rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.45)),
url("../images/hero.jpg") center/cover no-repeat;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
color: #fff;
}
.hero h1 {
font-size: 44px;
letter-spacing: 2px;
margin: 12px 0 24px;
}
.btn-primary {
display: inline-block;
background: #8c5b3f;
color: #fff;
padding: 12px 32px;
border-radius: 4px;
text-decoration: none;
transition: background 0.3s;
}
.btn-primary:hover {
background: #6d4c41;
}
这个渐变遮罩的写法简直是入门阶段性价比最高的技巧,效果直接、而且代码量少。很多同学会把遮罩写成一个单独的绝对定位div,没必要,两层背景图叠一起就行。
3.3 菜品卡片:网格布局的经典应用
首页和菜单页都离不开菜品卡片。这里用Grid布局比Flex更顺手,因为卡片数量不确定、换行时需要自动对齐。
html复制<section class="featured-dishes">
<h2>主厨推荐</h2>
<div class="dish-grid">
<article class="dish-card">
<img src="images/dish-1.jpg" alt="香煎三文鱼">
<div class="dish-info">
<h3>香煎三文鱼</h3>
<p class="dish-desc">配柠檬黄油汁与时蔬</p>
<div class="dish-footer">
<span class="price">¥88</span>
<button class="btn-order" data-dish="三文鱼">点餐</button>
</div>
</div>
</article>
<!-- 重复多张卡片 -->
</div>
</section>
Grid部分:
css复制.dish-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
max-width: 1200px;
margin: 0 auto;
padding: 24px;
}
.dish-card {
background: #fff;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
transition: transform 0.3s, box-shadow 0.3s;
}
.dish-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
}
.dish-card img {
width: 100%;
height: 200px;
object-fit: cover;
display: block;
}
.dish-info {
padding: 16px;
}
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)) 是响应式卡片列表的核心代码——不用写媒体查询,当屏幕变窄时列数会自动减少。object-fit: cover 确保不同尺寸的图片不会撑破卡片。这两行代码建议背下来,实用性极高。
3.4 JavaScript交互:轮播图与菜品筛选
铛铛,正菜来了。JavaScript部分我建议做两个功能就足够:一个轮播图,一个菜品筛选。如果还有余力,再加一个简单的"点餐"购物车列表。
轮播图的逻辑不复杂:一组图片,每隔几秒切换一张,同时提供左右按钮和底部小圆点。网上有各种插件,但大作业阶段强烈建议手写,因为真的不难,而且答辩时能清清楚楚讲出来。
javascript复制// js/main.js - 简易轮播图
const slides = document.querySelectorAll(".slide");
const dots = document.querySelectorAll(".dot");
const prevBtn = document.querySelector(".prev");
const nextBtn = document.querySelector(".next");
let current = 0;
let timer = null;
function showSlide(index) {
slides.forEach((s, i) => {
s.classList.toggle("active", i === index);
});
dots.forEach((d, i) => {
d.classList.toggle("active", i === index);
});
}
function nextSlide() {
current = (current + 1) % slides.length;
showSlide(current);
}
function prevSlide() {
current = (current - 1 + slides.length) % slides.length;
showSlide(current);
}
// 绑定事件
nextBtn.addEventListener("click", () => {
nextSlide();
restartAutoPlay();
});
prevBtn.addEventListener("click", () => {
prevSlide();
restartAutoPlay();
});
dots.forEach((dot, i) => {
dot.addEventListener("click", () => {
current = i;
showSlide(current);
restartAutoPlay();
});
});
// 自动播放与暂停
function startAutoPlay() {
timer = setInterval(nextSlide, 3000);
}
function restartAutoPlay() {
clearInterval(timer);
startAutoPlay();
}
showSlide(0);
startAutoPlay();
这里有个细节:手动点击之后自动轮播会"重置计时",不然会出现"刚点下一页,一秒又跳走"的割裂感。这个处理虽然简单,但很多入门教程根本不会提。
菜品筛选功能则利用 data-* 属性,把每个卡片标上分类,然后通过按钮切换显示。这个功能很适合做在菜单页:
html复制<div class="filter-bar">
<button class="filter-btn active" data-filter="all">全部</button>
<button class="filter-btn" data-filter="appetizer">前菜</button>
<button class="filter-btn" data-filter="main">主菜</button>
<button class="filter-btn" data-filter="dessert">甜品</button>
</div>
javascript复制// js/menu.js - 菜单筛选
const filterBtns = document.querySelectorAll(".filter-btn");
const menuCards = document.querySelectorAll(".menu-card");
filterBtns.forEach((btn) => {
btn.addEventListener("click", () => {
// 切换按钮高亮
filterBtns.forEach((b) => b.classList.remove("active"));
btn.classList.add("active");
const filter = btn.dataset.filter;
menuCards.forEach((card) => {
const category = card.dataset.category;
if (filter === "all" || category === filter) {
card.style.display = "block";
} else {
card.style.display = "none";
}
});
});
});
卡片HTML要加上 data-category="main" 这种属性,例如 <article class="menu-card" data-category="main">。这个方案的思路是"显示隐藏",而不是重新渲染DOM,逻辑简单可靠,性能对静态页面来说完全没问题。
4. 常见问题与避坑经验:写完不等于能完整运行
代码写完只是第一步。我把这些年同学们在交作业前最容易翻车的问题列一下,这些都是真实高频坑,建议对照自查。
4.1 图片路径和编码问题
第一个坑永远是路径。images/dish-1.jpg 是相对路径,如果你是从某地方复制图片,文件名可能是中文或带空格,浏览器解析会有问题。建议所有图片文件名统一改成英文小写连字符格式,例如 grilled-salmon.jpg,并在代码中保持一致。
第二个坑是编码。HTML文件开头务必加上 <meta charset="UTF-8">,不然中文可能显示成乱码。这个问题现在大多数编辑器新建文件会自动带,但手动从记事本写HTML时就容易漏。
4.2 关于版权和图片素材
大作业页面通常会配不少图片,千万不要直接去搜索引擎随便拽一张就放进项目里。一方面涉及版权问题,另一方面图片分辨率、风格都可能不统一,很掉档次。
推荐几个免费图库:Unsplash、Pexels、Pixabay。食物类素材非常充足,西餐摆盘图尤其多。下载时尽量选尺寸较大的,代码里用CSS控制显示大小,不要拿一张很小的缩略图硬拉伸成大图,会糊得没法看。
如果实在找不到完全满意的图,可以先放一张纯色的占位图,后期统一替换。不要在写代码阶段频繁换图,改路径特别容易出错。
4.3 雷同检测:一定要改模板的痕迹
现在的助教和老师对"模板感"非常敏感。什么是模板感?字体是默认的、布局是左右两栏、颜色是蓝白配、导航栏是灰底黑字——这些特征叠加起来,即使代码是你自己写的,也会被误认为模板。
我的建议是"局部定制":至少改三样东西——配色、字体引入方式、卡片样式。比如卡片不用直角边框,改成大圆角加阴影;按钮不用全宽,改成胶囊形或者细边框风格。这些CSS小改动足以让页面彻底摆脱初学模板的观感。
4.4 浏览器兼容性和测试
写完一定要在至少两个浏览器上过一遍,比如Chrome和Edge,有条件再用手机模式看一眼。有些CSS属性在不同浏览器的支持程度不一样,比如 backdrop-filter 在部分环境会有问题。不要慌,知道就行,测试时发现哪个页面乱了,优先用 display: flex、grid 这些最基础的能力去修。
另外,交作业前把整个文件夹复制一份到另一个位置,双击 index.html 打开验证一遍。有时候你在编辑器里打开没问题,但直接双击文件因为路径是 file:// 协议,某些资源加载方式会和本地服务器环境不一样。如果出现这种问题,最简单的做法是全程使用相对路径。
5. 答辩准备与项目讲解思路:怎么让老师觉得这是"你的作品"
最后这块容易被忽视,但恰恰很拉分。很多同学代码是真自己写的,一紧张就说不出来,或者讲的时候抓不住重点,东一下西一下。其实软件类课程答辩,老师想知道的无非三件事:你做了什么、怎么做出来的、遇到问题怎么解决的。
5.1 演示顺序推荐
打开首页,先花十秒钟介绍整体网站定位和风格("这是一个西餐主题的展示型网站,包含四个页面"),然后从首页往下滚,依次介绍Hero区、推荐菜品、评价区;切到菜单页,重点演示筛选功能,这里可以强调一下自己用了 dataset 加事件监听的方式实现分类切换;接着打开预订页,现场填一个表单演示校验逻辑;最后如果时间允许,展示一下页面在窄屏下的适配效果。
整个过程控制在三分钟到五分钟,重点的地方可以停下来提问:"这里我用了sticky定位,导航会始终显示在顶部。"
5.2 高频提问预先想好答案
我总结了几个出现频率最高的提问,你可以提前准备:
问:你觉得自己项目中哪个部分最难?
答法思路:不一定要说"很难",而是说"最有挑战的是XXX,比如轮播图的自动播放和手动切换会导致计时冲突,我通过重置定时器解决"。这个问题最怕回答"都挺简单的",显得没有深度思考。
问:为什么用Grid而不用Flex?
答法思路:Grid适合二维布局,比如卡片列表的行列控制非常方便;Flex适合一维排列,比如导航栏。我在卡片区域用Grid是因为它的 repeat(auto-fill, minmax(...)) 能自动适应列数。
问:如果让你继续扩展,你会做什么?
答法思路:可以说"加一个购物车模块,用localStorage保存数据""加一个后台管理页面"。重点是要答得具体、可落地,不要说空话。
平时把网页源码里的注释写得规范一些,不仅加分,也方便你答辩前快速回忆每个模块是干什么的。好的注释是写给未来的自己看的,不只是交给老师的。
5.3 一个小技巧:准备一张"设计说明"备注页
很多同学不知道这个,答辩时可以多做一步:在浏览器里开一个新建标签页,放一份简短的图文说明(或者直接在讲稿中附带),内容包括配色方案选择理由、字体选择理由、页面结构图。这个行为会让老师觉得你不只学了代码,还有一点产品设计的意识。对单纯的大作业来说,这是性价比极高的小亮点。
6. 写在最后:一个过来人的真心建议
说了这么多,其实最想分享的一点是:网页大作业是少数几个"投入产出比极高"的课程任务。它不需要你懂算法、不需要你背概念,只需要你花时间把每行代码吃透。哪怕你目前只是一个刚学前端两周的小白,只要按照页面规划、布局实现、交互功能、测试打磨这个顺序一步步走下来,完成一个八十多分的作品完全没问题。
我个人做了这些年技术分享,最大的感受就是静态网页就像做菜——食材(HTML)要新鲜,刀工(CSS)要精细,火候(JavaScript)要恰当。三者平衡好了,哪怕是"西餐美食网站"这种每年都有人做的老题目,也能做出让人眼前一亮的作品。如果你在做的过程中卡在哪个具体功能上,不妨先把自己写的代码贴出来逐行读一遍,很多时候问题出在最不起眼的地方。祝大家期末顺利,做出一份能大方展示的作品。
