ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

多页面网站前端实战:以南昌地铁官网20个页面为例

多页面网站前端实战:以南昌地铁官网20个页面为例 简介面向大学生与前端初学者的企业官网网页设计成品以南昌地铁为主题完整实现20个页面涵盖HTML5结构、CSS3样式与JavaScript交互适用于HTML5期末作业、Web前端课程设计及企业官网实战练习。压缩包共170个文件包含20个HTML页面、13个CSS样式表、15个JS脚本以及大量jpg/png/jpeg图片素材、SVG图标、字体、GIF、MP4和说明文档整体约54.42MB目录结构清晰便于直接部署与二次修改。页面涉及首页、线路导览、票价查询等模块包含轮播图、下拉菜单、响应式布局等常见交互价值在于提供一套可直接运行的企业官网完整方案帮助初学者理解多页面站点的信息架构、样式组织与脚本配合。已有210人学习使用适合需要快速完成期末作品或想学习整站开发流程的人群。1. 20 个页面的“期末作业”真正的考点是资源组织提到“南昌地铁官网 20 个页面”很多人第一反应是页面多、工作量大。但真正动手做过的人都知道20 个静态页面最耗时间的不是页面数量而是页面之间如何共用同一套样式、如何让轮播和日期选择这类第三方组件不互相打架、如何在 375px 到 1440px 的宽度范围里不出横向滚动条。这个基于 HTML5 CSS3 JavaScript 的地铁官网技术上没有复杂后端却把前端入门阶段该碰的问题都踩了一遍第三方 CSS 文件的加载顺序、公共导航的复用、页面级样式隔离、插件初始化时机。不管是为了完成大学生期末作业还是想把 web 前端多页面网页制作的基本功补齐照着这套结构拆一遍比单独做几个单页要有效得多。2. 从 style.css 到 nouislider.css拆开压缩包看技术选型拿到压缩包先不要急着双击index.html。把 CSS 文件列表过一遍会发现这套资源几乎是一个“标准企业官网前端工具链”style.css、hover-min.css、animate.css、font-awesome.min.css、bootstrap-datepicker.min.css、responsive.css、bootstrap-select.min.css、magnific-popup.css、owl.carousel.min.css、nouislider.css。光看文件名就能判断出项目里用了日期选择器、下拉选择、Magnific Popup 弹窗、Owl Carousel 轮播和 noUiSlider 滑块。这些并不是装饰而是官网“时刻表查询”“票价区间筛选”“车站实景图放大”这些功能的实现基础。2.1 先看 CSS 加载顺序层叠从 head 里就开始CSS 的层叠规则是“后面的覆盖前面的”所以 head 里的引入顺序决定最终渲染效果。这是 html 网页制作里最容易被忽略的一环。常见做法是先放工具类和插件样式再放项目自定义样式确保自己的规则能盖住第三方默认样式。!DOCTYPE html html langzh-cn head meta charsetutf-8 meta nameviewport contentwidthdevice-width, initial-scale1 title南昌地铁 - 首页/title !-- 第三方图标与动画 -- link relstylesheet hrefcss/font-awesome.min.css link relstylesheet hrefcss/animate.css !-- 第三方插件样式 -- link relstylesheet hrefcss/owl.carousel.min.css link relstylesheet hrefcss/magnific-popup.css link relstylesheet hrefcss/bootstrap-select.min.css link relstylesheet hrefcss/bootstrap-datepicker.min.css link relstylesheet hrefcss/nouislider.css !-- 本项目自定义样式 -- link relstylesheet hrefcss/style.css link relstylesheet hrefcss/hover-min.css link relstylesheet hrefcss/responsive.css /head这段代码的逻辑是Font Awesome 图标字体和 animate.css 动画类要最先可用因为后面所有 HTML 结构里都可能引用它们插件样式按“容器优先”的顺序排最后加载 style.css、hover-min.css 和 responsive.css。.min.css后缀代表压缩版本删掉了换行和空格加载体积更小。学习阶段为了能看懂源码可以换成未压缩版本部署时再换回 min 文件。2.2 每个文件的职责与选型理由把 10 个 CSS 文件按职责分一下类就得到一份“多页面官网样式资产表”。文件类型承担的功能典型页面style.css项目自定义全站布局、卡片、导航、配色全部页面hover-min.css微交互按钮和卡片鼠标移入时的动效服务介绍、首页animate.css入场动画元素滚动出现时的淡入和上移首页、关于我们font-awesome.min.css图标字体菜单、按钮、功能区图标全部页面bootstrap-datepicker.min.css表单插件乘车日期选择控件出行助手responsive.css项目自定义不同屏幕宽度下的适配修正全部页面bootstrap-select.min.css表单插件线路下拉搜索框的样式线路查询magnific-popup.css弹窗插件车站实景图放大查看站点详情owl.carousel.min.css轮播插件首页大图和新闻推荐滑动首页、资讯nouislider.css滑块插件票价区间筛选票价查询这里要注意bootstrap-datepicker 和 bootstrap-select 本身依赖 Bootstrap 的栅格和表单基础样式但如果压缩包里的 style.css 已经把这些基础样式合并起来了head 里就不需要单独再引一份 bootstrap.min.css。判断方法很简单在浏览器里打开任意一个带下拉框的页面看样式是否错位。错位就说明 style.css 顶部缺少 Bootstrap 核心样式需要补上。2.3 为什么不自己写这些插件不少同学做作业喜欢“纯手写”但在 20 个页面的规模下时间应该优先花在信息结构和响应式上。Owl Carousel 的触屏滑动和回弹效果手写至少几百行 JS 才能稳定复现Magnific Popup 处理了 ESC 关闭、焦点回退、图片预加载这些细节noUiSlider 在触摸端两个手柄不重叠的处理也很成熟。直接使用这些经过生产环境验证的组件是企业在做 web 前端时更常见的做法也是这个项目里最值得学习的一点不要重复造轮子把每个插件放在正确的场景里。2.4 hover-min.css 与“css 鼠标移入事件”“css 鼠标移入事件”是初学者经常搜索的说法但 CSS 里没有事件只有:hover伪类。hover-min.css 是 Hover.css 的压缩版它提供了一批现成的类名比如.hvr-sweep-to-right、.hvr-underline-from-left加到元素上就能产生扫过、下划线生长等效果。其实现和手写伪元素类似。.hvr-sweep-to-right { position: relative; overflow: hidden; } .hvr-sweep-to-right::before { content: ; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.06); transform: scaleX(0); transform-origin: left; transition: transform 0.3s ease-out; } .hvr-sweep-to-right:hover::before { transform: scaleX(1); }把hvr-sweep-to-right类加到导航按钮或卡片上鼠标移入时就会有一个从左向右扫过的蒙层。注意.hvr-sweep-to-right本身要设position: relative否则伪元素会脱离到页面左上角。用这个文件比在 style.css 里逐个写:hover要省事但对完全没看过源码的人出了问题不好排查所以至少要理解这类类名背后的结构。3. 20 个页面不写 20 份导航公共头尾复用与样式隔离多页面网站的导航和页脚如果靠复制粘贴改一次全站链接要打开 20 个文件重来一遍几乎等于灾难。处理思路是把 header 和 footer 抽成独立片段页面里只留一个占位标记加载完成后再把片段填进去。这个方案不依赖后端用纯 JavaScript 就能实现也可以在写完所有页面前先搭好框架后续新增页面成本很低。3.1 用 include.js 把 header 和 footer 变成可复用模块在项目根目录建一个components文件夹存放header.html和footer.html。header 里放完整的导航结构页面里只需要一行引用。!-- index.html -- body header>document.addEventListener(DOMContentLoaded, function () { var includes document.querySelectorAll([data-include]); includes.forEach(function (el) { var file el.getAttribute(data-include); fetch(file) .then(function (res) { if (!res.ok) { throw new Error(file 加载失败); } return res.text(); }) .then(function (html) { el.innerHTML html; }) .catch(function (err) { console.warn(公共头部/底部加载失败:, err); }); }); });这段逻辑是页面 DOM 解析完成后遍历所有带有>!-- index.html -- body>document.addEventListener(DOMContentLoaded, function () { var currentPage document.body.getAttribute(data-page); var navLinks document.querySelectorAll(.main-nav a); navLinks.forEach(function (link) { if (link.getAttribute(data-page) currentPage) { link.classList.add(current); } }); });用>/* 票价查询页自己的覆盖 */ .page-fare .panel { border-color: #2b6cb0; } .page-fare .price-range { margin: 24px 0 8px; } /* 线路列表页特殊缩进 */ .page-line-list .station-item { padding-left: 32px; }把覆盖范围限制在.page-fare或.page-line-list作用域内能避免页面之间的样式污染。这样写还有一个好处以后想单独调整某个页面的间距或配色不需要去全局样式里加一堆条件注释直接在对应作用域里改即可。3.4 给 CSS 和 JS 加版本号避免缓存干扰多页面网站最常见的“改了 CSS 不生效”问题大部分是浏览器缓存导致。常见做法是给静态资源加查询参数例如link relstylesheet hrefcss/style.css?v20260120 script srcjs/main.js?v20260120/script加版本号的原理是浏览器的 URL 变化会使缓存失效。每次发布前更新v参数就能强制用户拿到新样式。对于项目作业至少要在开发阶段理解这个机制否则后面调整复试样式时容易误判成代码问题。4. 把轮播、弹窗、日期选择、下拉和范围滑块的初始化串起来20 个页面的交互看起来分散但本质上都是一套初始化流程。这个项目里除了 noUiSlider 以外Owl Carousel、Magnific Popup、Bootstrap Datepicker、Bootstrap Select 都依赖 jQuery。如果在 main.js 里没有先确保 jQuery 已加载控制台会立刻报$ is not defined。所以 script 标签的引入顺序也应该遵循“jQuery 再插件再项目脚本”的规则。4.1 整合初始化代码main.js 的模块化写法我一般会在js/main.js里集中管理所有插件不把初始化代码散落在各个页面。这样可以减少重复代码排查问题时也只要看一个文件。(function () { function ready(fn) { if (document.readyState ! loading) { fn(); } else { document.addEventListener(DOMContentLoaded, fn); } } ready(function () { // 1. 首页轮播 if (document.querySelector(.owl-carousel)) { $(.owl-carousel).owlCarousel({ items: 1, loop: true, autoplay: true, autoplaySpeed: 800, nav: true, navText: [ i classfa fa-angle-left/i, i classfa fa-angle-right/i ], dots: true, responsive: { 768: { items: 2 }, 1200: { items: 3 } } }); } // 2. 车站图片弹窗 $(.popup-gallery).magnificPopup({ delegate: a, type: image, gallery: { enabled: true }, closeOnContentClick: true }); // 3. 乘车日期选择 $(.take-date).datepicker({ format: yyyy-mm-dd, todayHighlight: true, autoclose: true }); // 4. 线路下拉搜索 $(.select-line).selectpicker({ noneSelectedText: 请选择线路, liveSearch: true, size: 8 }); // 5. 票价区间滑块 var slider document.getElementById(fare-slider); if (slider window.noUiSlider) { noUiSlider.create(slider, { start: [2, 8], connect: true, step: 1, range: { min: 2, max: 13 } }); slider.noUiSlider.on(update, function (values) { document.getElementById(fare-range).textContent values[0] 元 - values[1] 元; }); } }); })();这段代码的核心思路是用ready函数模拟document.ready的兼容处理再逐个判断页面中是否存在对应容器存在才初始化对应插件。每个插件前加 DOM 判断不仅能避免无关页面多执行无意义的初始化还能防止容器不存在时插件报错导致后续 JS 中断。navText里使用 Font Awesome 图标替代默认文字箭头是官网视觉统一时比较顺手的方法。4.2 插件参数怎么改重点参数对照很多初学 JavaScript 的同学拿到一段初始化代码能运行但不知道怎么改成自己需要的效果。这里把常用参数单独列出来。插件常用参数作用与调整思路owlCarouselitems / loop / autoplay / navTextitems 控制每屏数量loop 设为 false 时第一张不能往前循环owlCarouselresponsive按断点覆盖 items适合首页多栏目卡片轮播magnificPopupdelegate / gallery / typedelegate 必须指向实际触发弹窗的链接type 决定用图片还是内联内容datepickerformat / autoclose / todayHighlightformat 建议与后端接口要求的日期格式一致避免提交时二次转换selectpickerliveSearch / size / noneSelectedText超过 10 个站点建议开启 liveSearch否则下拉太长noUiSliderstart / connect / range / stepstart 是初始区间connect 为 true 表示两端滑块之间的区域填充颜色调整参数时把值改掉刷新页面就能看到效果。比如票价区间如果改成 2 到 15 元只需要修改range里的max: 15滑块末端位置会自动变化start里的初始值也必须落在range范围内否则滑块会被钳制到边界。4.3 跨页面传条件URL 参数替代 JS 全局变量线路查询页和票价查询页都可能出现“选择条件后跳转到结果页面”的场景。如果直接在 JS 里定义变量跳转后变量就丢失了常见做法是把条件拼接到 URL 后面。function goResult() { var line $(#line-select).val(); var date $(.take-date).val(); location.href result.html?line encodeURIComponent(line) date encodeURIComponent(date); }在 result.html 里再解析function getUrlParam(name) { var params new URLSearchParams(location.search); return params.get(name); } var line getUrlParam(line); var date getUrlParam(date); if (line) { $(#result-hint).text(当前线路 line 乘车日期 date); }encodeURIComponent的作用是把中文和特殊字符转成 URL 安全格式避免?line1号线date...中的中文导致解析错乱。URLSearchParams是现代浏览器内置的 URL 解析 API比手写 split 处理要清晰得多。4.4 JS 报错先看执行顺序项目里最容易出现的三个错误是$ is not defined、$(...).owlCarousel is not a function、noUiSlider is not defined。第一个是 jQuery 没加载或路径写错第二个是插件 JS 文件被放在 jQuery 之前加载导致插件没有注册到$.fn上第三个是 nouislider 的 JS 文件没有引入而 main.js 里又用到了window.noUiSlider。排查时打开开发者工具控制台看第一条红色报错再配合 Network 面板确认文件是否 404通常几分钟就能定位。5. 响应式断点、样式覆盖链和最后一道验证这个项目的 responsive.css 不是独立重写整套布局而是把 Bootstrap 风格断点下的“修正”集中放一起。20 个页面如果每个都在 style.css 里堆媒体查询文件会越来越难维护把响应式修正单独拆分出来是合理的设计。5.1 responsive.css 的断点策略常见做法是向上兼容为主小屏修正为辅。media (min-width: 768px) { .page-home .banner-caption { top: 30%; } } media (min-width: 992px) { .line-sidebar { position: sticky; top: 20px; } } media (max-width: 767px) { .navbar-toggle { display: block; } .mobile-menu { overflow-x: auto; -webkit-overflow-scrolling: touch; } }用min-width写桌面增强页面在 768px 以上的平板和桌面都能获得相同增强用max-width写移动端专属修正。两种写法混用时要特别小心顺序因为后面min-width可能会覆盖前面max-width里的相同属性。5.2 常见响应式翻车现场多页面官网最容易出现三个响应式问题。第一是轮播图在小屏下高度塌陷Owl Carousel 多列模式下单张图片高度不一致解决办法是给轮播图设置固定高度并让图片按object-fit: cover裁剪。第二是 flex 布局中子项不收缩导致横向溢出给子项加min-width: 0通常能解决。第三是 selectpicker 在窄屏下把下拉菜单撑到屏幕外限制下拉面板宽度并开启liveSearch可以明显减少误触。5.3 验证响应式不能只靠拖动浏览器窗口Chrome 开发者工具的 Device Toolbar 里预置了 Moto G4、iPhone SE、iPhone 12 Pro 等真实设备尺寸逐个打开主要页面检查导航是否遮挡内容、页面是否存在横向滚动条。如果觉得逐个页面翻太慢可以在控制台手动跑一段检查脚本。document.querySelectorAll(*).forEach(function (el) { if (el.scrollWidth document.documentElement.clientWidth) { console.warn(横向溢出元素, el, el.scrollWidth); } });这段代码的逻辑是遍历页面上所有元素把元素的scrollWidth和视口宽度做对比。一旦某个元素内容超宽就说明导致横向滚动条的根因在这里。这个脚本在开发阶段随时可以手动执行不建议直接写进生产环境页面避免影响用户性能。5.4 看懂“是谁改了我的样式”在票价查询页里如果想修改下拉框圆角可能会遇到自己写的样式不生效。Chrome DevTools 的 Elements 面板右侧 Styles 列表会按优先级从高到低展示所有匹配规则被划掉的就是被后面的规则覆盖掉的声明。解决顺序是先确认style.css确实在插件 CSS 之后加载再用更高优先级的选择器例如.page-fare .dropdown-menu而不是直接给规则加!important。只有理解了层叠和选择器特异性才能真正控制 20 个页面里的每一处细节。本文还有配套的精品资源点击获取
返回列表