大鱼海棠主题网页期末作业:HTML+CSS+JS从结构到交互完整实践
2026/9/16 16:57:26 网站建设 项目流程

简介:这是一套以“大鱼海棠”为主题的网页期末作业完整源码包,面向需要提交 HTML5 响应式网站作业的高校学生,也适合初学者临摹页面布局与交互。项目采用 div+css+js 的常规前端结构,共 215 个文件、约 23.62MB,包含 10 个 html 页面、9 个 css 样式表、12 个 js 脚本,以及 160 张 png/jpg 图片素材;另有 less 预编译文件、字体图标与少量动画库配置,分别承担主题视觉、响应式布局和页面动效。作者按 Dreamweaver 的建站习惯对文件夹和代码书写做了整理,目录按页面和资源分类,便于对照学习、局部替换或作为课程设计底稿。压缩包内附项目配置与字体等辅助文件,打开即可直接预览整套页面效果,适合期末检查前快速梳理页面跳转与样式分工。目前已有 8070 人学习,适合希望快速获得结构规范、视觉完整的期末网站范例,并进一步巩固前端基础的学生使用。

1. 网页期末作业选“大鱼海棠”主题,HTML+CSS+JS 怎么分工最合理

网页期末作业最怕的不是功能少,而是在答辩时被问“这个效果是怎么实现的”答不上来。用“大鱼海棠”做主题单页站,恰好把前端三件套各用一遍:HTML负责内容语义,CSS负责国风质感,JS负责交互反馈。不引框架、不碰构建工具,一个浏览器加一个编辑器就能跑,能应付“必须使用原生HTML/CSS/JS”的课程要求,也容易被追问时现场演示。下面的方案按常见检查流程排,先搭结构,再调样式,最后补交互,每一步都给出能直接复制运行的代码、参数说明和失败排查点。整套做下来代码量控制在几百行内,讲得完,也守得住。

2. 页面骨架与整体布局:把“大鱼海棠”拆成可实现的网页模块

做网页之前先回答一个问题:不依赖任何框架,单纯用 HTML+CSS+JS 能稳定呈现这个主题的哪些视觉元素?答案通常落在四个模块上:大字标题首屏、电影故事介绍、人物卡片、场景轮播。这四个模块对应了期末作业常见评分点里的“结构完整、样式丰富、交互合理”。

2.1 先定页面层级,再写 HTML 代码

“大鱼海棠”的视觉印象集中在暗色夜空、红色主调、金色点缀、大海与土楼。把印象转成页面层级时,我会用如下顺序排列:

  • hero 首屏:大标题、副标题、漂浮大鱼动画
  • story 章节:电影设定文案,配背景图
  • characters 章节:椿、湫、鲲三张人物卡片,带悬浮效果
  • gallery 章节:场景轮播,三张图自动播放
  • footer 页脚:署名和课程信息

顺序确定后,HTML 只需要撑出骨架,样式和交互全部通过 class 挂钩。这样后期改样式不用动结构,改结构也不会弄坏 JS 选择器。

2.2 先写语义化 HTML 骨架,再考虑样式

下面这份 HTML 是整站的内容骨架,省略了图片资源和具体文案,只保留结构关系:

<header class="site-header" id="siteNav"> <div class="header-inner"> <a href="#hero" class="logo">大鱼海棠</a> <nav class="nav-menu"> <a href="#story">电影介绍</a> <a href="#characters">人物</a> <a href="#gallery">场景</a> </nav> </div> </header> <main> <section id="hero" class="hero"> <h1 class="hero-title">大鱼海棠</h1> <p class="hero-subtitle">所有活着的人类,都是海里一条巨大的鱼</p> <div class="hero-fish" aria-hidden="true"></div> </section> <section id="story" class="story"> <h2>故事与世界观</h2> <p>这里填写电影剧情设定的两到三句话,期末作业中这段文字也是考察点,建议自己组织语言后再放上去。</p> </section> <section id="characters" class="characters"> <h2>主要人物</h2> <div class="card-list" id="cardList"> <article class="card">:root { --bg-deep: #0e0b14; /* 页面底色:夜空般的深紫黑 */ --bg-section: #151021; /* 区块底色:比底色略亮,拉开层次 */ --red-main: #8d2a24; /* 主红:标题强调、边框、按钮 */ --gold-accent: #d9a86c; /* 金色:分割线、hover 高亮 */ --text-main: #f0e6d6; /* 正文:米白,避免纯白刺眼 */ --text-dim: #9a8f86; /* 弱化文字:注释、辅助信息 */ }

为什么不直接在所有规则里写色值?因为期末作业再简单也要考虑可维护性。答辩时如果被问“想整体调亮或调暗怎么办”,直接改--bg-deep--bg-section两个变量即可,其他规则自动生效。表格里每个变量的职责在注释中已经写明,这本身就是代码规范的一部分。

布局上建议给main里的 section 统一最大宽度和水平内边距:

main section { max-width: 1080px; margin: 0 auto; padding: 60px 24px; }

加上这段之后,所有章节在不同宽度屏幕下都能保持居中且左右留白,后续写样式时不需要每节重复设置宽度。对期末作业这种规模的项目,够用了。

3. 仿国风质感的 CSS 细节:字体渐变、伪类选择器、鼠标移入和关键帧动画

“大鱼海棠”题材的网页,最容易出彩的地方在标题文字和卡片交互。这一章只做一件事:把视觉质感堆在 CSS 层,不需要 JS 参与。CSS 能做好的交互就不要交给 JS,这是减少 bug 的第一原则。

3.1 标题文字做字体渐变:background-clip 的用法

大字标题如果只是白色粗体,撑不起“大鱼海棠”五个字的气场。常见做法是给文字加一个从米金到暗红的渐变,代码很简洁:

.hero-title { font-size: clamp(2.6rem, 8vw, 5rem); font-weight: 700; letter-spacing: 0.15em; background: linear-gradient(180deg, #f5d0a9 0%, #e8b07d 45%, #a33a2e 100%); -webkit-background-clip: text; background-clip: text; color: transparent; }

这段样式的核心是background-clip: text。它让渐变背景按照文字形状被裁剪,再把文字颜色设为transparent,视觉上就出现渐变字效果。注意必须同时保留-webkit-background-clip前缀,部分基于 Chromium 的浏览器虽然也支持标准属性,但实际渲染中仍然存在需要前缀的场景。

失败排查点:如果标题变成完全透明或整块色块,先确认两件事——color: transparent是否被后面的规则覆盖;background-clip: text是否被写进了错误的简写顺序里。把渐变色单独抽出来放到 background 属性上,能明显降低排查难度。

3.2 伪类选择器与鼠标移入事件:卡片悬浮效果

很多搜索流量指向“css 鼠标移入事件”和“css伪类选择器怎么用”,这里做一个明确区分:鼠标移入的默认样式反馈,用 CSS 的:hover伪类选择器就够了;只有需要在移入时改变 DOM 结构或联动其他元素,才考虑 JS 事件。

给人物卡片加悬浮反馈,思路是两层组合:默认状态下设置过渡,hover状态下修改transform和边框颜色:

.card { background: var(--bg-section); border: 1px solid rgba(217, 168, 108, 0.25); border-radius: 12px; padding: 24px; transition: transform 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease; } .card:hover { transform: translateY(-6px) scale(1.02); border-color: var(--gold-accent); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35); }

transition 写在:hover里是常见错误。写在默认状态里,移入和移出两种方向都有过渡动画;写在:hover里,移出时会瞬间弹回,观感突兀。transform这里只做位移和缩放两个维度,位移让卡片有“浮起”感,缩放不要超过 1.05,否则边框会显得粗糙。

伪类选择器还可以用在排列上。三张人物卡片如果要在不同数量时保持间距均匀,:not(:last-child)比手写 margin 更省心:

.card-list { display: flex; gap: 24px; } .card-list .card:not(:last-child) { margin-bottom: 0; } @media (max-width: 720px) { .card-list { flex-direction: column; } }

这里:not(:last-child)用于 PC 端横向排列时避免给最后一张卡加多余间距;移动端切纵向排列后,间距由 flex 的gap统一负责。用一个伪类就省掉三个 margin 冗余声明。

3.3 关键帧动画让“鲲”游起来:transform 优先原则

首屏需要一个能让人一眼记住的动效。“大鱼”游过夜空是主题页的标配,实现方式不需要图片素材,一个渐变圆角块加关键帧动画即可:

.hero-fish { width: 120px; height: 60px; background: radial-gradient(ellipse at 30% 40%, #d9a86c, #8d2a24); border-radius: 60% 60% 40% 40%; animation: swim 12s ease-in-out infinite alternate; } @keyframes swim { from { transform: translateX(-10vw) translateY(0) scale(0.9); opacity: 0.6; } to { transform: translateX(90vw) translateY(-20px) scale(1.1); opacity: 1; } }

动画参数说明:12s是单个动画周期时长;“大鱼”游速要慢,8 到 14 秒之间比较符合主题的高空质感。infinite alternate让动画来回游而不是重置到起点后跳变。ease-in-out让首尾速度放缓,中间匀速,模拟滑行感。

性能上的关键点请记住:动画只写transformopacity,不要写lefttopmargintransform可以走独立合成层,浏览器不需要反复计算布局,这在低配笔记本上跑轮播和游鱼动画时差距非常明显。期末答辩时能说出这一条,已经比大多数直接把动画写在left上的同学领先一个维度。

下表是 transition 与 animation 的适用场景对比:

类型触发条件循环能力典型场景
transition属性变化时被动触发不能循环卡片 hover、按钮反馈、导航背景变化
animation页面加载后主动执行可循环、可交替大鱼游动、轮播淡入、背景缓慢漂浮

4. 让页面动起来:JS 轮播组件、返回顶部算法与字符串过滤

CSS 做完质感,JS 负责三个交互:滚动监听导航背景、场景轮播、按关键词过滤人物卡片。这三个点分别命中“导航跟随”“轮播图”“搜索过滤”,是期末作业里最常被追问的交互,也是 JS 这门课的成绩分水岭。

4.1 滚动监听导航栏:scrollY 与 classList 的配合

导航栏默认透明,页面下滑超过 60px 后变成带底色,这是单页站最常见的细节处理:

const siteNav = document.getElementById('siteNav'); window.addEventListener('scroll', () => { siteNav.classList.toggle('nav-scrolled', window.scrollY > 60); }, { passive: true });

classList.toggle的第二个参数是布尔值,为 true 时加 class,为 false 时移除。用这个写法比先if判断再用add/remove更简洁,而且滚动事件里不会写多余逻辑。passive: true告诉浏览器这个监听器不会调用preventDefault,滚动性能不会因为多余的拦截检查而下降。

配套 CSS 只需要给.nav-scrolled增加背景色和阴影:

.site-header { position: fixed; top: 0; left: 0; right: 0; z-index: 100; background: transparent; transition: background 0.3s ease; } .site-header.nav-scrolled { background: rgba(14, 11, 20, 0.92); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); }

注意header设了position: fixed,页面内容会被盖住,所以给main的第一个区块加一个顶部内边距,比如.hero { padding-top: 120px; },否则首屏标题会被导航遮挡。

4.2 不依赖插件的轮播组件:索引取余与 translateX

轮播是期末作业的重头戏。这里实现一个纯 JS 版本,三张场景图自动轮播,支持左右按钮切换:

<div class="carousel-viewport"> <div class="carousel-track"> <div class="slide"></div> <div class="slide"></div> <div class="slide"></div> </div> </div> <button class="carousel-btn prev">上一张</button> <button class="carousel-btn next">下一张</button>

CSS 核心是让 track 内的每张 slide 宽度占满视口且不压缩:

.carousel-viewport { overflow: hidden; } .carousel-track { display: flex; transition: transform 0.4s ease; } .slide { min-width: 100%; height: 360px; background-size: cover; background-position: center; }

JS 控制索引和位移:

const track = document.querySelector('.carousel-track'); const slides = document.querySelectorAll('.slide'); const total = slides.length; let index = 0; let timer = null; function goTo(i) { index = (i + total) % total; track.style.transform = `translateX(-${index * (100 / total)}%)`; } document.querySelector('.carousel-btn.next').addEventListener('click', () => { goTo(index + 1); restartAutoPlay(); }); document.querySelector('.carousel-btn.prev').addEventListener('click', () => { goTo(index - 1); restartAutoPlay(); }); function restartAutoPlay() { clearInterval(timer); timer = setInterval(() => { goTo(index + 1); }, 4000); } restartAutoPlay();

参数说明:index = (i + total) % total是关键技术点。当 index 等于 total 时取余回到 0,当 index 等于 -1 时取余回到 total - 1,循环边界无需写 if 分支。translateX的百分比是相对于 track 自身宽度而不是视口宽度,track 被三张 slide 撑开后自身宽度等于三个视口宽,所以要移动一个视口宽需要移动100 / total个百分比的 track 宽度。写成index * (100 / total)而不是index * 100,这个细节明白的话,任意张数的轮播都能套用。

4.3 一键返回顶部的两种实现与“算法”边界

“html一键返回顶部算法”这类搜索词背后的需求其实很简单:点按钮平滑回到顶部,且按钮在页面顶部时隐藏。先给一个现代浏览器的标准写法:

const backToTop = document.getElementById('backToTop'); backToTop.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); window.addEventListener('scroll', () => { backToTop.classList.toggle('active', window.scrollY > 400); }, { passive: true });

window.scrollTo配合behavior: 'smooth'是浏览器原生平滑滚动方案,代码最少,不用自己管理动画帧。但注意部分旧环境不支持 smooth,这时可以用 requestAnimationFrame 手动实现一个带缓动的版本:

function scrollToTopSmooth(duration = 400) { const startY = window.scrollY; const startTime = performance.now(); if (startY === 0) return; function step(now) { const progress = Math.min((now - startTime) / duration, 1); const eased = 1 - Math.pow(1 - progress, 3); window.scrollTo(0, Math.round(startY * (1 - eased))); if (progress < 1) { requestAnimationFrame(step); } } requestAnimationFrame(step); }

1 - Math.pow(1 - progress, 3)是 easeOutCubic 缓动函数,前快后慢,符合“快速回到顶部”的直觉。Math.min(..., 1)保证进度不超过 1,避免最后一帧回弹。duration = 400是 400 毫秒,超过这个时长会显得拖动感过强。实际使用时优先用原生scrollTo,手动版本作为答辩时“我能讲清楚动画帧机制”的加分项。

4.4 用 JS 判断字符串是否包含,给人物列表做过滤

热词“js判断字符串是否包含”落到这个题目里的对应场景是:搜索框输入关键词,人物卡片列表实时过滤。String.prototype.includes是这里的主角:

const searchInput = document.getElementById('searchInput'); const cards = document.querySelectorAll('.card'); searchInput.addEventListener('input', () => { const keyword = searchInput.value.trim().toLowerCase(); cards.forEach((card) => { const name = card.dataset.name.toLowerCase(); card.hidden = !name.includes(keyword); }); });

逻辑说明:trim()去掉输入两端的空格,避免用户多敲一个空格导致匹配失败;toLowerCase()统一大小写,让“chun”和“Chun”都能匹配;includes返回布尔值,作为 hidden 属性的赋值可直接生效。用card.hidden = true而不是card.style.display = 'none',是因为 hidden 是 HTML 标准属性,语义更清晰且优先级不会被外部样式干扰。

这里要提醒一个细节:includes是区分大小写的,所以两侧都要先toLowerCase();中文内容调用toLowerCase()不影响原值,但如果人物卡片里有英文拼音或外文名,这行就必不可少。

5. 收尾检查与答辩提分:兼容性细节、动画帧验证和无障碍降级

代码写完不等于作业能交。最后这一章给出三个能直接落地的收尾动作,分别对应兼容性、性能和可访问性。

5.1 三个必改的兼容性细节

用表格总结期末作业里最常见的三个“本地跑正常、换机器就崩”的问题:

问题现象改法
background-clip: text未加前缀标题文字透明或显示整块渐变矩形保留-webkit-background-clip: text,再写标准属性
scroll-behavior: smooth被忽略点击锚点瞬间跳转html上声明;或用 JS 的scrollTo({behavior: 'smooth'})兜底
图片撑破卡片卡片尺寸被图片拉伸图片用object-fit: cover或改用背景图加background-size: cover

第一条已经在 3.1 提过,这里是交作业前必须复查的清单化版本。第二条“被忽略”通常不是浏览器不支持,而是平滑滚动需要写在html元素上而不是body

html { scroll-behavior: smooth; }

5.2 在浏览器开发者工具里验证动画流畅度

期末作业被追问“你确定动画不卡吗”时,最好的回答是用事实说话。常见做法是在页面按 F12 打开开发者工具,切换到 Performance 面板,点击录制后操作轮播和滚动,几秒后停止录制,查看红框标出的帧耗时段落。一帧超过 16.7ms 意味着低于 60 FPS,需要检查是否有引起重排的属性变更。

用代码验证也是可行的。在轮播的 goTo 函数中加入一段临时耗时统计:

const start = performance.now(); track.style.transform = `translateX(-${index * (100 / total)}%)`; console.log('切换耗时:', performance.now() - start, 'ms');

这段临时代码只用于自查,测量的是从设置 transform 到 JS 执行完同步操作的时间,不包括渲染管线完整耗时。它的意义在于排查 JS 侧是否存在明显瓶颈,真正的渲染流畅度仍以 Performance 面板为准。

5.3 一个加分收尾:prefers-reduced-motion 降级动画

当用户系统开启了“减少动态效果”时,动画应该被降级。在样式表末尾加一段媒体查询,一行代码兼容所有动画:

@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } }

这段代码将动画和过渡时长压到接近 0,用户不会看到平移和闪烁。0.01ms 而不是 0,是为了避免部分浏览器将 0 判定为无效值而回退到默认时长。把它配合前面讲到的transform合成层优化一起放进答辩词里,就是两个能主动说出口的技术细节。轮播、返回顶部和卡片悬浮的交互齐全,渐变标题和游鱼动画各有明确实现原理,这套“大鱼海棠”单页作业就可以进入演示了。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询