拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

网页设计期末作业完整实战:HTML5+CSS3+JavaScript响应式布局与表单验证

网页设计期末作业完整实战:HTML5+CSS3+JavaScript响应式布局与表单验证

简介:这是面向网页设计课程作业与期末项目考核的一套个人博客风格源码包,帮助初学前端或非计算机专业的学生理解网页构成与设计流程。站点包含首页、信息页、列表页与关于页四个页面,基于HTML结构化标记、CSS样式表与Div盒模型布局实现,从页面骨架到模块样式再到脚本交互,链条完整,适合直接对照修改。压缩包共53个文件、整体大小45.44MB,文件构成上以19张jpg图片、5个css样式表、6个js脚本和4个html页面为主体,图片素材覆盖页面视觉元素,css拆分管理不同模块样式,js实现滚动动画、吸顶与菜单等交互,另附演示入口,可在线预览页面实际渲染效果。目前已有7366人学习下载。四个HTML页面分别承担首页展示、信息承载、内容列表与个人介绍功能,信息架构清晰;base.css、info.css等分模块样式文件便于理解类命名与布局组织方式,适合逐一拆解代码,既能完成课程作业,也能积累真实个人博客项目的设计与开发经验。

1. 网页设计期末作业:一份能直接复现的完整项目与演示

网页设计作业是每学期末最磨人的一关——老师要的不是你用了多少框架,而是页面结构清不清晰、CSS 布局稳不稳、交互逻辑能不能跑通。我见过太多同学把大把时间耗在调一个轮播图上,结果交上去连页面滚动都卡。这篇笔记拆的是一份「带演示」的网页设计期末作业项目,HTML5 + CSS3 + 原生 JavaScript 完成,不依赖任何框架和构建工具,浏览器打开即用。它覆盖了个人主页、响应式导航、卡片式内容区、表单验证和简单的本地存储交互,正好对应课程大纲里那几个必考模块。新手能照着一行行敲下来,熟手可以直接拿它的页面骨架改出自己的主题配色和内容区。

2. 拆解作业评分逻辑:先搞懂老师按什么给分,再动手写代码

2.1 一份期末作业的典型评分构成

网页设计课期末作业的评分表,不同学校略有差异,但核心维度基本是这几块:页面数量与结构完整性、HTML 标签语义化程度、CSS 样式与布局实现方式、JavaScript 交互功能,以及最后的现场演示效果。注意,这里特意列了「布局实现方式」而不是「布局效果」——因为很多老师会问你是用 Flex 还是 Grid,用浮动还是定位,如果你说“我是用 Dreamweaver 拖出来的”,那这题基本就凉了。

把评分构成拆开看,我一般建议按下面这个权重分配精力:

评分项权重参考需要交付的内容
页面结构与数量20%至少 3 个互相跳转的页面,或单页多区块
HTML 语义化15%header、nav、main、section、footer 等标签用对
CSS 布局与响应式30%Flex/Grid 布局、媒体查询、自适应断点
JavaScript 功能25%表单验证、交互事件、数据渲染
演示与答辩10%打开页面、操作流程顺畅,不出低级错误

为什么把 JS 的权重定得这么高?因为课程后半学期的重点就在 DOM 操作和事件处理上。作业里哪怕只有一个「点击按钮切换主题色」的功能,也比五个静态页面积分来得快。但前提是——这个功能必须能跑,不能是贴了代码自己都不明白的「黑匣子」。

2.2 选型:为什么用纯 HTML/CSS/JS 而不是 Vue 或 Bootstrap

如果你问上过这门课的学长,十有八九会劝你别用框架。原因很现实:期末作业的答辩环节,老师会随机指一个页面区块,问“这个效果是怎么实现的”。你答「Vue 的 v-for 渲染的」,老师再问“那 v-for 的 key 为什么不能用 index”,多数人就卡住了。用原生三件套,每个效果对应哪几行代码,自己心里是有数的。

这份项目选的也是纯原生方案。CSS 布局用的是 Flex 和 Grid 混排——导航栏和卡片列表用 Flex,整体页面大骨架用 Grid。响应式断点只设了两个,一个 768px 的平板断点,一个 480px 的手机断点。JavaScript 部分也没上任何库,原生querySelector、addEventListener、localStorage三件套打底。这样的好处是,项目文件放到 U 盘里,换任何一台电脑,只要浏览器是 Chrome 或 Edge,双击 index.html 就能跑。

2.3 文件组织方式:一个文件夹该放什么

期末作业的文件组织,直接影响到老师打开你项目时的第一印象。我见过有人把所有图片和页面全堆在根目录,文件名还是新建文档(2).html,这种印象分基本就没了。这份项目的文件结构是这样的:

web-final-project/ ├── index.html # 首页 ├── about.html # 关于页面 ├── portfolio.html # 作品集页面 ├── css/ │ ├── style.css # 全局样式 │ └── responsive.css # 响应式断点样式 ├── js/ │ ├── main.js # 全局交互:导航、主题切换 │ └── form.js # 表单验证与本地存储 ├── images/ │ ├── hero-bg.jpg # 首屏背景图 │ └── portfolio-1.jpg ~ portfolio-6.jpg # 作品占位图 └── README.txt # 项目说明与运行方式

这里有个小细节:单独拆一个responsive.css,而不是把媒体查询写在 style.css 底部。原因很实际——答辩时老师问「你的响应式在哪实现的」,你可以直接翻到这一个文件里讲,比在几百行样式里来回翻要省事得多。而且单独文件也方便检查断点之间的覆盖关系。

3. 从零搭一套页面骨架:首页结构与导航的完整实现

3.1 首页的 HTML 结构:语义化标签怎么排

首页是整个作业的门面,结构合理性大于视觉效果。我们先把index.html的头部和主体骨架搭出来。注意看每个标签的嵌套关系,以及class的命名方式——类名统一用main-container、card-grid这种描述性名称,不要用box1、div2。

<!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"> <link rel="stylesheet" href="css/responsive.css"> </head> <body> <header class="site-header"> <nav class="main-nav"> <div class="logo"> <a href="index.html">MySite</a> </div> <ul class="nav-links"> <li><a href="index.html" class="active">首页</a></li> <li><a href="about.html">关于我</a></li> <li><a href="portfolio.html">作品集</a></li> <li><a href="index.html#contact">联系我</a></li> </ul> <button class="nav-toggle" id="navToggle" type="button"> <span class="toggle-bar"></span> <span class="toggle-bar"></span> <span class="toggle-bar"></span> </button> </nav> </header> <main> <section class="hero" id="home"> <div class="hero-content"> <h1>你好,我是前端学习者</h1> <p>这是基于 HTML5 + CSS3 + JavaScript 制作的期末作业项目</p> <a href="portfolio.html" class="btn-primary">查看我的作品</a> </div> </section> <section class="features" id="features"> <h2>本站包含的模块</h2> <div class="card-grid"> <article class="card"> <h3>响应式导航</h3> <p>移动端通过按钮切换菜单展开与收起</p> </article> <article class="card"> <h3>表单验证</h3> <p>原生 JavaScript 实现必填项与格式校验</p> </article> <article class="card"> <h3>本地存储</h3> <p>localStorage 保存用户访问记录</p> </article> </div> </section> </main> <footer class="site-footer"> <p>&copy; 2024 网页设计期末作业项目</p> </footer> <script src="js/main.js"></script> </body> </html>

这段结构里的几个关键点:header内只放导航,main里是英雄区(hero)和特性卡片区(features),footer放版权信息。HTML5 的语义化标签不仅是为了让老师看到你会用,更重要的是让页面结构在没有 CSS 的时候依然可读——这也在评分表里。

nav里的四个链接中,「联系我」指向的是index.html#contact,这是锚点定位,跳转到本页的联系表单区块。这个写法帮助很大——你不需要单独做一个联系页面,一个锚点就能让结构多一个层级。

3.2 移动端导航:汉堡按钮的 JavaScript 实现

桌面端导航是横排的,到移动端得折叠成汉堡菜单。这部分的 JavaScript 逻辑很简单,但有一个容易踩的坑:菜单展开后点击空白区域不会自动收起。这份项目的处理是监听按钮点击来切换active类,同时通过addEventListener监听resize事件,在窗口变宽时强制移除折叠状态。

// js/main.js document.addEventListener('DOMContentLoaded', function () { const navToggle = document.getElementById('navToggle'); const navLinks = document.querySelector('.nav-links'); // 汉堡按钮点击:切换菜单展开/收起 navToggle.addEventListener('click', function () { navLinks.classList.toggle('nav-links-open'); navToggle.classList.toggle('toggle-active'); }); // 点击导航链接后自动收起菜单(移动端体验优化) navLinks.querySelectorAll('a').forEach(function (link) { link.addEventListener('click', function () { navLinks.classList.remove('nav-links-open'); navToggle.classList.remove('toggle-active'); }); }); });

这段代码的事件绑定思路是:navToggle按钮负责切换样式类,navLinks的展开状态由nav-links-open类来控制。之所以不直接改display属性,是因为我们想保留过度动画——在 CSS 里给.nav-links设置了max-height的过渡。第二段 forEach 循环是细节优化,移动端点完链接后菜单能自动收起,不然每次跳完回来看屏幕都被菜单盖住,演示时非常尴尬。

4. CSS 布局与响应式:Flex、Grid 和媒体查询的配合实战

4.1 全局样式与 CSS 变量:让换配色变成改一行代码

很多同学写 CSS 喜欢把颜色写死在每个选择器里,比如.card { background: #f7f7f7; }。这样一旦答辩时老师问「把主色调成暗色系要改几个地方」,你就得一个个翻。更好的做法是用 CSS 变量统一管颜色,这份项目在style.css开头定义了全套视觉变量:

/* css/style.css */ :root { --primary-color: #2563eb; /* 主色:用于按钮、导航高亮 */ --secondary-color: #f59e0b; /* 辅助色:用于强调标签 */ --bg-light: #f8fafc; /* 浅色背景 */ --bg-dark: #0f172a; /* 深色背景(页脚和移动端菜单) */ --text-main: #1e293b; /* 正文文字颜色 */ --text-muted: #64748b; /* 次要文字颜色 */ --card-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); --border-radius: 12px; --nav-height: 64px; --transition-speed: 0.3s; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif; color: var(--text-main); background: var(--bg-light); line-height: 1.7; } a { text-decoration: none; color: inherit; } img { max-width: 100%; display: block; }

CSS 变量的好处不是让你少写几行代码,而是让全局风格统一到一个入口里。后面做暗色模式也好,小组作业换成员配色也好,改:root里的变量就行。box-sizing: border-box是必须加的,不加的话子元素的width: 100%加上padding会把父容器撑破,这是新手最容易翻车的一个点。

4.2 卡片区域用 Grid,导航栏用 Flex:两种布局的分工

布局部分,最核心的决策是搞清楚什么场景用 Flex,什么场景用 Grid。这份项目里的.card-grid是典型的网格布局——三张卡片等宽排列,换行时保持对齐,Grid 的repeat(auto-fit, minmax())配合媒体查询非常顺手。而.main-nav里的 logo 和菜单链接需要一个水平排列的弹性容器,Flex 更合适。

先看卡片区的 Grid 写法:

/* css/style.css */ .card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 24px; padding: 20px 0; } .card { background: #ffffff; border-radius: var(--border-radius); box-shadow: var(--card-shadow); padding: 28px; transition: transform var(--transition-speed), box-shadow var(--transition-speed); } .card:hover { transform: translateY(-6px); box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12); }

grid-template-columns: repeat(auto-fit, minmax(240px, 1fr))这一行是精髓:minmax(240px, 1fr)表示每个卡片最小 240px 宽,空间足够时均分剩余宽度;auto-fit则是在容器宽度不足以放下更多卡片时自动换行。也就是说——你没有写一行媒体查询,Grid 自己就把响应式做了。这是一个非常值得在答辩时展示的细节。

再看导航栏的 Flex:

/* css/style.css */ .main-nav { display: flex; align-items: center; justify-content: space-between; height: var(--nav-height); padding: 0 24px; background: #ffffff; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); position: sticky; top: 0; z-index: 100; } .nav-links { display: flex; align-items: center; gap: 32px; list-style: none; } .nav-links a { font-size: 15px; font-weight: 500; padding: 6px 0; border-bottom: 2px solid transparent; transition: border-color var(--transition-speed), color var(--transition-speed); } .nav-links a:hover, .nav-links a.active { color: var(--primary-color); border-bottom-color: var(--primary-color); }

position: sticky让导航栏吸顶,这是比fixed更优雅的方案——fixed会让导航脱离文档流,页面顶部内容会被遮挡一截;sticky不会。需要注意的是,sticky 生效的前提是父容器高度大于导航栏自身高度,且父容器没有设overflow: hidden,否则吸顶会失效。这是布局黑盒里最常见的一个坑。

4.3 响应式断点:媒体查询里的层叠顺序问题

这份项目的responsive.css单独管理断点样式。移动端的核心切换逻辑在max-width: 768px断点内,把导航菜单从横排变成下拉展开:

/* css/responsive.css */ @media (max-width: 768px) { .nav-toggle { display: flex; flex-direction: column; justify-content: center; gap: 5px; width: 40px; height: 40px; background: none; border: none; cursor: pointer; } .toggle-bar { width: 24px; height: 2px; background: var(--text-main); transition: transform var(--transition-speed), opacity var(--transition-speed); } .nav-links { position: absolute; top: var(--nav-height); left: 0; right: 0; flex-direction: column; background: var(--bg-dark); padding: 16px 24px; max-height: 0; overflow: hidden; transition: max-height var(--transition-speed) ease-in; } .nav-links.nav-links-open { max-height: 320px; } .nav-links a { color: #e2e8f0; display: block; padding: 12px 0; } }

媒体查询的层叠顺序必须注意:如果这段代码写在style.css前面,会被后面的样式覆盖掉。所以建议要么把responsive.css放在各页面<head>里的最后,要么在 CSS 文件内部把媒体查询放到文件末尾——原因是媒体查询本身并不增加特异性,它靠的是「后出现的规则胜出」。另外这里用了max-height: 0到max-height: 320px的过渡——过渡只能作用在数值型属性上,用display: none到display: block是不会有动画的。

5. JavaScript 交互与表单验证:从能跑到不翻车的完整闭环

5.1 表单验证:正则、防早提交、错误提示联动

作业页面里的联系表单,是最容易被老师挑刺的模块。最常见的翻车是:用户没填手机号,点击提交按钮后没有任何反应,老师以为功能坏了。这份项目的表单校验做了三件事:失去焦点时即时校验、提交时整体校验、错误提示用span标签动态插入。先看 HTML 结构里有对应错误提示位置的写法:

<form id="contactForm" novalidate> <div class="form-group"> <label for="name">姓名</label> <input type="text" id="name" name="name" required placeholder="请输入姓名"> <span class="error-message" id="nameError"></span> </div> <div class="form-group"> <label for="email">邮箱</label> <input type="email" id="email" name="email" required placeholder="请输入邮箱"> <span class="error-message" id="emailError"></span> </div> <div class="form-group"> <label for="phone">手机号</label> <input type="tel" id="phone" name="phone" required placeholder="请输入11位手机号"> <span class="error-message" id="phoneError"></span> </div> <div class="form-group"> <label for="message">留言内容</label> <textarea id="message" name="message" rows="4" required placeholder="请输入留言内容"></textarea> <span class="error-message" id="messageError"></span> </div> <button type="submit" class="btn-primary" id="submitBtn">提交留言</button> </form>

novalidate属性很关键——它告诉浏览器「不要用默认的 HTML5 提示气泡,让我自己控制校验反馈」。默认气泡在不同浏览器里长不一样,而且一旦出现,你自己的错误提示逻辑就被绕过了。对应的 JavaScript 校验逻辑:

// js/form.js document.addEventListener('DOMContentLoaded', function () { const form = document.getElementById('contactForm'); const submitBtn = document.getElementById('submitBtn'); // 正则规则定义 const validators = { name: function (value) { return value.trim().length >= 2 ? '' : '姓名至少需要2个字符'; }, email: function (value) { const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; return emailRegex.test(value.trim()) ? '' : '请输入正确的邮箱格式'; }, phone: function (value) { const phoneRegex = /^1[3-9]\d{9}$/; return phoneRegex.test(value.trim()) ? '' : '请输入正确的11位手机号'; }, message: function (value) { return value.trim().length >= 5 ? '' : '留言内容至少需要5个字符'; } }; // 校验单个字段并更新错误提示 function validateField(field) { const id = field.id; const errorSpan = document.getElementById(id + 'Error'); const errorMsg = validators[id](field.value); errorSpan.textContent = errorMsg; field.classList.toggle('input-error', Boolean(errorMsg)); return errorMsg === ''; } // 每个输入框失焦时单独校验 form.querySelectorAll('input, textarea').forEach(function (field) { field.addEventListener('blur', function () { validateField(field); }); }); // 提交按钮点击时,先校验再决定是否放行 submitBtn.addEventListener('click', function (e) { e.preventDefault(); let allValid = true; form.querySelectorAll('input, textarea').forEach(function (field) { const isValid = validateField(field); if (!isValid) { allValid = false; } }); if (allValid) { // localStorage 存储提交记录 const records = JSON.parse(localStorage.getItem('contactRecords') || '[]'); const newRecord = { name: document.getElementById('name').value.trim(), email: document.getElementById('email').value.trim(), phone: document.getElementById('phone').value.trim(), message: document.getElementById('message').value.trim(), time: new Date().toLocaleString() }; records.push(newRecord); localStorage.setItem('contactRecords', JSON.stringify(records)); form.reset(); alert('提交成功!\n你的留言已保存在本地浏览器中。'); } else { const firstError = form.querySelector('.input-error'); if (firstError) { firstError.focus(); } } }); });

这段代码的三个处理习惯值得说明:一是提交按钮用的是click事件而不是submit事件,配合e.preventDefault()拦截默认提交行为,这样所有逻辑都在自己的控制流里走;二是每条校验规则是一个纯函数,输入值和正则,返回空字符串或错误信息,方便后续加新字段时复制粘贴;三是把提交记录写入localStorage——这个设计让「表单提交」升级成了「数据持久化」,答辩时可以说你的页面能保存用户留言记录,刷新后还在(用localStorage.getItem再渲染出来)。

5.2 localStorage 的应用:保存主题偏好与访问记录

表单里已经把数据写进了 localStorage,这个能力还能再延伸一下。比如做一个「记住我的主题选择」——用户点了暗色模式切换按钮,刷新页面后依然是暗色。实现思路是在main.js里加一段主题切换逻辑:

// js/main.js 追加 const themeToggleBtn = document.getElementById('themeToggle') || null; if (themeToggleBtn) { // 初始化时读取本地存储中的主题 const savedTheme = localStorage.getItem('siteTheme'); if (savedTheme === 'dark') { document.body.classList.add('dark-theme'); } themeToggleBtn.addEventListener('click', function () { document.body.classList.toggle('dark-theme'); const currentTheme = document.body.classList.contains('dark-theme') ? 'dark' : 'light'; localStorage.setItem('siteTheme', currentTheme); }); }

注意document.getElementById('themeToggle') || null的写法——如果某个页面没有这个按钮,脚本不会因为拿不到元素而报错中断。这个习惯在多个页面共用一个 JS 文件时尤其重要。之前有人就是因为about.html里没有navToggle元素,整个main.js直接抛异常,后面的代码全部不执行。

5.3 演示时最常见的 JS 翻车点

表单和 localStorage 的逻辑跑通之后,演示环节真正的风险反而不是功能本身,而是环境问题。最常见的三种翻车:一是直接双击打开index.html,地址栏是file:///C:/...,这种情况下 localStorage 在某些浏览器版本里是可用但隔离的,但如果 HTML 里有跨文件请求(比如分别用file://打开不同页面),各页面之间的 localStorage 共享可能出问题;二是浏览器缓存了旧版 JS,改完代码刷新还是不生效;三是控制台有红字报错但你没打开控制台看,演示到一半才发现。

解决办法是:演示前强制刷新(Ctrl + Shift + R),并且提前打开 F12 控制台看一眼有没有报错。这个「检查控制台」的习惯,能救回大部分现场翻车。

6. 避坑与常见问题:网页设计作业的五个高频雷区

6.1 图片路径写错导致页面破版

现象:本地打开时所有图片正常显示,把文件夹拷到 U 盘拿到别的电脑上演示,图片全部裂了。

原因:图片路径写了绝对路径,比如<img src="C:\Users\张三\Desktop\images\hero.jpg">,或者用了file:///开头的路径。换一台电脑路径就失效了。

解决:所有资源一律用相对路径。同一个项目文件夹里,index.html引用images/hero.jpg时直接写images/hero.jpg,页面在sub子目录里则写../images/hero.jpg。拷文件夹时连同整个项目目录一起拷,不要只拷 html 文件。

6.2 CSS 里position: sticky吸顶失效

现象:导航栏原本应该吸在顶部,滚动页面时却跟着内容滚走了。

原因:sticky的生效条件是父容器的高度大于导航栏高度,且祖先元素没有设置overflow: hidden或overflow: auto。很多模板在body或外层容器上加overflow-x: hidden来隐藏横向滚动条,这个操作会让sticky直接失效。

解决:检查父容器和body的overflow属性。如果要隐藏横向溢出,把overflow-x: hidden加在body上但不要在父容器上重复设置;实在不行,改用position: fixed配合body的padding-top补偿导航栏高度。

6.3 移动端菜单点不开,或点开后关不掉

现象:手机模拟器里点汉堡按钮,菜单没有反应;或者菜单展开后,点击菜单外面的区域无法收起。

原因:按钮的click事件没绑上,常见原因是navToggle元素不存在时 JS 报错阻断后续代码;或者 CSS 里.nav-links的max-height设置成了0,内容被overflow: hidden裁掉,但 JS 里加的nav-links-open类在选择器优先级上被别的规则覆盖了。

解决:先在 Console 里执行document.getElementById('navToggle'),看返回的是元素还是null。如果是null,检查 HTML 里的id是否和 JS 里一致。优先级问题则用选择器ul.nav-links.nav-links-open明确指定。

6.4 表单提交后页面刷新导致数据丢失

现象:点提交按钮后,页面闪了一下,输入的内容全没了,localStorage 里也没有记录。

原因:点击按钮的默认行为触发了表单原生提交,整个页面重新加载了。你虽然加了e.preventDefault(),但可能写在了submit事件上而按钮是type="submit"之外的问题——实际上更常见的是按钮没有加type="button"属性,或者监听的事件写在了form的submit上但没阻止成功。

解决:在form上加submit事件监听并e.preventDefault(),按钮保持type="submit";或者直接给按钮加type="button",用click事件处理。两种方案二选一,不要混用。我的习惯是用click事件加type="button",这样控制流最简单。

6.5 演示时临时改代码,现场乱了阵脚

现象:演示前老师说“把这个按钮颜色改成红色看看”,你打开 CSS 找到.btn-primary,改了background属性,结果页面没有任何变化。

原因:浏览器缓存了旧的 CSS 文件。有的场景下老师网速、或你用的是学校机房的旧浏览器,对 CSS 文件有强缓存,不刷新不生效。

解决:改代码后按Ctrl + Shift + R强制刷新(清除缓存刷新),或者干脆到 CSS 文件路径后面加一个版本号参数:<link rel="stylesheet" href="css/style.css?v=2">。加版本号参数的方式在期末答辩场景里更稳妥,改一次加一次v=2、v=3,能保证每次拿到的都是最新样式。

7. 演示提分技巧:答辩前花 20 分钟过一遍这四步

演示环节不是把页面点开就完事了,老师在这几分钟里看的是你的熟练度和对代码的理解。我自己的习惯是答辩前必做四件事,每一件都用不了几分钟,但能挡住大部分意外。

第一件事:打开 Chrome 的无痕窗口。无痕窗口默认不带任何缓存和插件干扰,F12 控制台如果是干净的,基本能排除「浏览器环境问题」这个变量。直接在无痕窗口里打开index.html,这能避开旧缓存导致的样式错乱。

第二件事:过一遍导航的所有跳转。从首页点到关于页,再从关于页点到作品集页,每个链接都点一次,确认没有 404。尤其要注意锚点跳转——index.html#contact这种链接,如果页面里没有id="contact"的元素,点下去页面不会有任何反应,老师会以为导航坏了。

第三件事:把窗口从宽拉到窄,展示响应式过程。按住窗口边缘慢慢拖窄,让老师看到导航栏从横排变成汉堡按钮、卡片从三列变成一列的连续过程。这一步是视觉冲击力最强的演示,但前提是你自己先拖了一遍,确认断点在 768px 处切换顺畅,没有中间态样式错乱。

第四件事:现场演示改一个「主题色变量」。打开style.css的:root部分,把--primary-color: #2563eb改成--primary-color: #dc2626(红色),保存后刷新。整个页面的按钮、高亮、导航下划线全部变成红色。这是一个演示「CSS 变量威力」的绝佳动作——老师会直观看到你不是在硬编码颜色,而是有一个统一的设计系统。这个动作在答辩环节能拿到的印象分,比多做一个轮播图高得多。

另外确认一下localStorage的演示路径:先填表单提交一条留言,然后 F5 刷新页面,再点开控制台执行:

// 在 Console 面板中执行,查看已保存的留言记录 const records = JSON.parse(localStorage.getItem('contactRecords') || '[]'); console.log(records);

执行后能看到刚才提交的记录数组,包含姓名、邮箱、手机号和提交时间。这样老师在看到「表单提交成功」之外,还会看到你额外实现了数据持久化。

从那以后,我每次交网页设计作业前都强制走一遍这套演示流程——无痕窗口、导航全点、窗口拉窄、改 CSS 变量。这四步做完,现场翻车的概率至少降一半。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表