简介一份基于HTML、CSS与JavaScript的静态旅游网站源码适合前端初学者、网页设计爱好者及需要快速搭建旅游展示页的开发者参考使用。压缩包共173个文件主要包含24个htm页面、18个css样式、20张jpg图片、85个gif动图及少量swf/js文件整体仅872KB结构轻量、便于本地预览与二次修改。目前已有2518人学习下载。源码覆盖常见的旅游站点场景如景点介绍、旅游套餐、预订表单等样式上利用CSS实现导航特效与响应式布局JavaScript用于轮播图、弹出窗口及表单验证同时包含对图片优化、SEO元标签、W3C规范注释等细节的处理。通过阅读和运行这些静态页面能够直观理解前端三大技术的协作方式并掌握从页面结构到交互效果的完整实现思路适合作为课程设计或个人练习的参考模板。1. 为什么还要找 html静态旅游网站源码静态站在旅游展示场景里的底气你手上有一个旅游目的地、一条周边游线路或者一家民宿想做一个看得过去的展示页面预算不高、又不想碰后端。搜 html静态旅游网站源码 搜到的大多是“能下载能跑”的完整网页——首页、景点卡片、详情、图片画廊都齐了。这类纯静态站点没有数据库、没有接口依赖放到任意支持静态文件的服务器上就能打开首屏速度通常比同体积的动态站点快一个量级。它不是给大型在线旅游平台用的而是给个人博主、小型旅行社、学生课程设计这类“展示优先”的场景。静态站最大的价值是确定性和低成本一个 HTML 文件加一套 CSS/JS改文字、换图片就能交付。你不需要关心服务端语言也不用为并发发愁出问题的概率被压到最低。接下来我会从页面骨架讲到代码实现再到部署前的性能优化过程中会把图片路径、响应式坑、编码问题这些容易翻车的点单独拿出来说。目标是让照着做的读者拿到一套能改、能交付、能讲清原理的代码而不是只会复制粘贴。2. 动手前先定骨架静态旅游网站的页面结构与资源规划2.1 页面清单与信息架构一个最小旅游站由哪几页组成静态网站很容易“写着写着就乱”因为每个页面都是独立文件没有后端模板帮你统一样式。我的习惯是先画一张页面关系图再动手。一个能满足大多数展示场景的旅游站最少需要三页首页品牌展示 目的地入口、列表页浏览多个目的地、详情页单个景点的图文介绍。页面之间用导航串起来首页和列表页互相跳转列表页的卡片点击后进入详情页详情页提供“返回列表”的链接。到此为止不需要第四层页面。像“关于我们”和“联系方式”我通常建议合并到首页底部用锚点定位实现而不是单独建页。这样文件数量和跳转关系都能稳住。另外文件名用英文小写、多个单词用连字符分隔这一条要提前定死。例如 beijing-detail.html 这种命名在部署到 Linux 服务器后会少很多麻烦因为 Windows 本地不区分大小写而 Linux 区分这个细节后面第 5 章会展开。这里先记住目录和文件统一小写英文不用中文名。2.2 目录结构与图片资源规划把页面、样式、图片分开是底线直接给出一份我常用的目录结构照着建就行travel-site/ ├── index.html ├── destinations.html ├── detail.html ├── assets/ │ ├── css/ │ │ └── style.css │ ├── js/ │ │ ├── main.js │ │ └── gallery.js │ └── images/ │ ├── hero/ │ │ └── hero-main.jpg │ ├── spots/ │ │ ├── spot-mountain.jpg │ │ ├── spot-lake.jpg │ │ └── spot-town.jpg │ └── icons/ │ └── arrow.svg这个结构里有几个约定值得记一下。CSS 和 JS 分别放在自己的目录下避免根目录散落一堆文件图片按用途再细分 hero首屏大图和 spots景点卡片图将来换图时不用在一堆文件里翻。icons 文件夹专门放 SVG 图标因为图标文件小、复用次数高单独放后期好维护。开发阶段就把图片统一压缩到“宽不超过 1280 像素”这是很多人不愿意早期做、后期被迫返工的事。一张相机原图可能 8MB在移动网络上加载要好几秒而同样内容压缩到 200KB 以内观感几乎无差别。图片处理的选型参数可以参考下表图片用途推荐格式最大宽度目标大小质量建议Hero 首屏背景JPEG / WebP1920px300KB 内60%景点卡片图JPEG / WebP1280px200KB 内70%-80%图标 / 装饰SVG / PNG不自限20KB 内无损画廊大图JPEG / WebP1600px400KB 内75%提示开发时不要直接从微信截图或手机相册里拖原图进项目先过一遍压缩流程再放进来否则导航栏背景、卡片图片会把整站首屏拖慢。3. 核心页面拿代码说事首页、列表页与详情页的最小实现3.1 首页 Hero 区与导航栏第一版能跑通的 index.html首页是网站的“门面”首屏导航 Hero 大图 一句行动口号决定了访客是否往下滚动。先给出一版精简但完整的首页 HTML!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 meta namedescription content山野漫游——提供周边小众旅行目的地推荐与路线攻略 title山野漫游 | 发现身边的风景/title link relstylesheet hrefassets/css/style.css /head body header classsite-header div classlogo a hrefindex.html山野漫游/a /div nav classmain-nav ul lia hrefindex.html classactive首页/a/li lia hrefdestinations.html目的地/a/li lia hrefdetail.html?id1景点详情/a/li /ul /nav /header section classhero h1周末出发走进山野/h1 p精选 20 条周边小众路线人少景美说走就走/p a hrefdestinations.html classbtn-primary查看目的地/a /section section classintro h2我们做什么/h2 p这个网站是静态旅游页面的示例项目所有内容在浏览器本地加载不依赖任何服务器接口。适合用来了解一个纯前端站点如何组织页面、样式与交互。/p /section /body /html这段代码的关键点有三个。第一meta nameviewport是移动端自适应布局的基础缺失会直接导致手机浏览器按 980 像素宽度渲染页面整个布局瞬间“缩小到看不清”。第二导航里用classactive标记当前页面方便 CSS 高亮这是多页静态站统一做法。第三Hero 区的背景大图我没有写在 HTML 里而是打算放到 CSS 中用背景图方式实现这样图片路径集中管理后面也方便做响应式替换。图片在静态站里分两种角色装饰性图片走 CSS 背景内容性图片走img标签。Hero 背景、图标属于装饰性景点照片属于内容性。这一原则能让响应式调整轻松不少因为装饰图可以用 CSS 媒体查询直接换内容图则要依赖 HTML 的 alt 和 loading 属性做 SEO 与性能优化。现在这个页面还没有样式是“裸”结构可以打开浏览器确认导航链接能来回跳转再进入样式阶段。3.2 目的地卡片网格列表页如何承载大量景点内容列表页是旅游站的“货架”用户在这里浏览目的地并选择点进哪个。这一页的核心是用 CSS Grid 布局做卡片网格用 JavaScript 做基础筛选。先看 HTML!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title目的地列表 | 山野漫游/title link relstylesheet hrefassets/css/style.css /head body header classsite-header div classlogoa hrefindex.html山野漫游/a/div nav classmain-nav ul lia hrefindex.html首页/a/li lia hrefdestinations.html classactive目的地/a/li lia hrefdetail.html?id1景点详情/a/li /ul /nav /header section classpage-title h1全部目的地/h1 div classfilter-bar button classfilter-btn active>!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title云顶山详情 | 山野漫游/title link relstylesheet hrefassets/css/style.css /head body header classsite-header div classlogoa hrefindex.html山野漫游/a/div nav classmain-nav ul lia hrefindex.html首页/a/li lia hrefdestinations.html目的地/a/li lia hrefdetail.html?id1 classactive景点详情/a/li /ul /nav /header section classdetail-hero h1云顶山/h1 p classdetail-meta徒步难度中等 | 最佳季节春夏 | 游玩时长1 天/p /section section classgallery img srcassets/images/spots/spot-mountain.jpg alt云顶山全景 classgallery-thumb>// 获取所有画廊缩略图 const thumbs document.querySelectorAll(.gallery-thumb); const lightbox document.getElementById(lightbox); const lightboxImg document.getElementById(lightbox-img); const closeBtn document.getElementById(lightbox-close); // 点击缩略图把>/* assets/css/style.css —— 基础变量与公共样式 */ :root { --primary-color: #2a7f6e; --primary-dark: #1f5f52; --text-color: #333333; --bg-light: #f7f9f8; --card-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); --radius: 12px; --max-width: 1200px; --header-height: 64px; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, Segoe UI, PingFang SC, Microsoft YaHei, sans-serif; color: var(--text-color); background: var(--bg-light); line-height: 1.6; } .site-header { height: var(--header-height); display: flex; justify-content: space-between; align-items: center; padding: 0 24px; background: #ffffff; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); position: sticky; top: 0; z-index: 100; } .main-nav ul { display: flex; list-style: none; gap: 20px; } .main-nav a { text-decoration: none; color: var(--text-color); font-size: 15px; padding: 6px 12px; border-radius: 6px; transition: background 0.2s; } .main-nav a:hover { background: var(--bg-light); } .main-nav a.active { color: #ffffff; background: var(--primary-color); }--primary-color是主题色这里用了偏森林绿的#2a7f6e旅游类网站常用蓝绿、暖黄这类带自然感或温度感的色系。如果你拿到一份旅游网站源码想换主题色只需要改:root里的变量表不用进每个页面搜索颜色值。box-sizing: border-box是重置项几乎所有现代项目都会加避免 padding 把固定宽度撑破。需要注意position: sticky的 header 在滚动时会“吸”在顶部这是浏览器原生能力不需要 JS。但 sticky 有一个前提——它的父级不能有overflow: hidden否则会失效。如果导航栏没有吸顶第一件事就是检查 header 或 body 上有没有 overflow 相关样式这个坑在第 5 章还要专门展开。4.2 卡片网格的响应式实现一套 Grid 适配三种屏幕列表页的卡片网格是整站信息密度最高的区域响应式做不好就是灾难。我直接给出经过验证的网格方案.card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; max-width: var(--max-width); margin: 0 auto; padding: 24px; } .card { background: #ffffff; border-radius: var(--radius); overflow: hidden; box-shadow: var(--card-shadow); transition: transform 0.2s ease, box-shadow 0.2s ease; } .card:hover { transform: translateY(-4px); box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12); } .card img { width: 100%; height: 200px; object-fit: cover; display: block; } .card-body { padding: 16px; } /* 平板两列 */ media (max-width: 768px) { .card-grid { grid-template-columns: repeat(2, 1fr); } } /* 手机单列 */ media (max-width: 480px) { .card-grid { grid-template-columns: 1fr; } .card img { height: 180px; } }这套写法的关键在于grid-template-columns: repeat(3, 1fr)配合两个媒体查询断点768px 以下变两列480px 以下变单列。object-fit: cover是最容易被忽略的一条没有它不同比例的图片会把卡片撑得高一块矮一块有了它图片会被等比裁剪填满 200px 高度框卡片之间保持整齐。如果图片比例差异特别大比如有的横图有的竖图我一般会在源头把图片统一裁成 3:2 比例再放进项目。依靠object-fit是保底方案源头统一是更舒服的方案。两者同时做页面才不会出现“一半卡片图被裁掉主体”的尴尬。4.3 三个高性价比交互滚动渐入、返回顶部、筛选按钮静态站想要一点动态感又不引入框架原生 JS 足够。这里把三个高频交互放在 main.js 里逻辑可以独立复用。// assets/js/main.js —— 滚动渐入与返回顶部 (function() { // 1. 滚动渐入给元素加 .fade-in 类进视口后显示 const fadeEls document.querySelectorAll(.fade-in); const observer new IntersectionObserver(function(entries) { entries.forEach(function(entry) { if (entry.isIntersecting) { entry.target.classList.add(visible); observer.unobserve(entry.target); // 只触发一次 } }); }, { threshold: 0.2 }); fadeEls.forEach(function(el) { observer.observe(el); }); // 2. 返回顶部按钮 const backTopBtn document.getElementById(back-top); if (backTopBtn) { backTopBtn.addEventListener(click, function() { window.scrollTo({ top: 0, behavior: smooth }); }); // 滚动超过 400px 才显示按钮 window.addEventListener(scroll, function() { backTopBtn.hidden window.scrollY 400; }); } // 3. 列表筛选按 style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />