前阵子清理移动硬盘,翻出来一个编号11857的旧文件夹,里面是两年前我刚开始学前端时做的一个影剧网页项目。所谓“影剧网页”,就是用HTML把喜欢的影视剧信息整理成能浏览的页面,包括剧照、简介、评分、演职员表和预告片入口。当时没有用任何框架,也没有构建工具,就是一个index.html配一个style.css,外加几个详情页。做完之后发给几个朋友看了下,大家觉得这个练习特别适合刚接触HTML的人。所以这次我把整个制作过程拆出来,讲讲基于HTML的影剧网页制作到底怎么一步步落地,包括信息结构、语义化标签、图片与视频的处理、多页面跳转,以及最后的调试和上线。
1. 项目缘起:为什么我要手写一个影剧网页
1.1 从追剧备忘录到网页
我平时追剧有个习惯:看到别人推荐,先截个图存手机,或者记在备忘录里。时间一长,备忘录里攒了几十部影视剧,有悬疑的、有科幻的、有古装的。想找一部周末看,翻半天目录还是乱的。刚好那时候在系统学HTML,老师出了一个练习:任意做一个主题页面。我就想,与其做一个关于猫咪、美食的常规页面,不如直接把自己那份剧单做成网页。这样既能练手,又能顺手解决信息整理的问题。项目编号我顺手写成了11857,纯属当时的笔记序号。
后来这个项目越做越顺手,我才发现一件很关键的事:很多人学HTML时都愿意跟着视频里的教程做“仿某某网站首页”,但教程页面通常和自己的生活没什么关系,做完就忘。可一旦把HTML用在真实需求上,比如管理自己真正想看的剧,你会主动去想“这个信息该放在哪一层”“用户先看什么后看什么”。这种主动思考恰恰是入门阶段最需要的,比多敲几行代码重要得多。
1.2 为什么不直接装个App,而是要写HTML
可能有人会说:现在随便找个影评类App或者Excel表格就能管理片单,何必写网页?我当时也认真考虑过。App确实方便,但信息被锁在某个App里,想分享给朋友,对方还得装同一个软件;Excel能排序筛选,但样式单调,而且手机上打开体验不好。HTML页面则不同:一个纯静态页面放到任何静态托管服务上,分享一个链接就能打开,不需要装客户端,不用登录,打开就有内容。
更重要的是,写这个页面的过程能让我把HTML的常用标签全部过一遍:标题、段落、列表、表格、图片、链接、表单、区块划分,几乎全涉及。这种“为了真实需求而写代码”的效果,比对着教程敲十遍都管用。而且HTML本身非常宽容,写错了也不会报错崩溃,最多是显示效果不对。对新手来说,这种试错成本很低的语言,恰好适合用来建立信心。
1.3 我打算把页面做成什么样
在动手之前,我先定了一个最小可行版本:一个首页,叫index.html,里面以卡片网格的形式展示六部剧;点击每张卡片,进入对应的详情页,比如detail-01.html。详情页包含头部导航、大剧照、基本信息、剧情简介、演职员表格、预告片区域,以及底部“返回首页”和相关推荐。因为只有两个层级,站点规模很小,不需要数据库,也不需要动态脚本。
整个项目以HTML为骨架,配一份外部CSS负责视觉效果。如果你完全不想写CSS,只靠HTML也能传达内容,只是排版会比较原始。这一点在后面的内容里再展开,先记住:HTML负责的是“结构”,CSS负责“长相”,JavaScript负责“交互”。标题虽然叫“基于HTML”,但现实中的网页很少完全不用CSS,你至少要会一点基础样式才能让页面可读。我后面把CSS放在一个独立文件里,HTML里通过link标签引入,这样内容和表现分离,结构更干净。
2. 先定信息架构:把一张追剧清单变成页面蓝图
2.1 写代码前先列内容清单
我见过太多初学者一上来就写标签,写到一半发现漏了字段、又改结构,非常痛苦。做页面和装修房子很像,先有设计图再施工。我先把每部剧需要的信息全部列出来:剧名、导演、主演、类型、地区、语言、首播年份、集数、评分、剧情简介、一句话看点、剧照、预告片链接。然后我按照重要程度排了序:剧名、剧照、评分和类型是让人快速判断“要不要看”的信息,放最显眼的位置;演职员和简介是进一步信息;预告片是决策前最后一步。
这个优先级直接决定了首页卡片和详情页各区块的先后顺序。卡片上只保留四个元素:封面、剧名、类型与年份、评分。这样扫一眼就能知道“这是什么、值不值得看”。完整的导演、主演和详细介绍全部放到详情页,避免首页信息过载。我自己的体感是:信息架构阶段花的时间越多,后面写HTML的速度越快,改结构的次数也越少。
2.2 两个页面的职责划分:让用户少点一次
首页解决的是“有哪些剧可选”,详情页解决的是“这部剧怎么样”。所以首页的卡片不需要放全文简介,放剧名、年份、类型、评分和一个封面就足够了,再多就是冗余;详情页才放完整的演职员表和预告片。当时我还加了一个“观剧状态”字段,比如“已完结”“连载中”“待补”,放在卡片角落,用于提醒自己哪部还没补完。页面职责一旦划分清楚,写标签的时候就不会犹豫该把某段内容放到哪个页面。
举一个例子:一开始我曾打算在首页卡片里放大段简介,后来发现六七张卡片全都排得很长,往下翻很累。改成只保留一句话看点后,页面清爽多了。这个取舍就是信息架构的意义——你不是在塞内容,而是在帮用户做筛选。详情页则相反,用户已经做出了点击行为,说明他有兴趣,所以可以放心地提供完整的演职员表、分集简介、预告片等信息。
2.3 文件目录怎么组织,后期维护不头疼
由于项目小,文件结构可以平铺,但尽量分文件夹:
filmdemo/ ├── index.html ├── detail-01.html ├── detail-02.html ├── css/ │ └── style.css ├── images/ │ ├── cover-01.jpg │ └── poster-detail-01.jpg └── video/ └── trailer-01.mp4images放封面和大图,video放预告片,css放样式。HTML文件之间只隔一层,相对路径写起来比较简单。比如在detail-01.html里引用图片,写images/cover-01.jpg就行,不需要../images。如果你把文件放在不同层级,比如按剧集分子目录,那么链接路径就要多留意。建议小项目先用扁平结构,等页面多了再重构。
还有一点容易被忽略:文件名尽量都用小写字母、数字和连字符,不要用中文名或含空格的名称。因为有些服务器严格区分大小写,而且中文文件名在分享链接时会转成长串字符,非常难看。目录名和文件名一旦定下来,后面尽量不要乱改,不然所有引用都要跟着变。
3. 核心标签搭建:剧集简介、评分和演职员表该怎么写
3.1 先理解语义化标签:不要见到内容就放div
在写HTML的时候,最大的一个坑是全程用div。div本身没有含义,但搜索引擎和读屏软件是靠标签本身来理解页面结构。如果全用div,页面看起来没问题,别人读的时候就像看一张没有标题层级的大报纸。为了体现文档结构,我用了header、nav、main、section、article、aside、footer这一套语义化标签。其中main表示当前页面的主体内容,一个页面只有一个main;article表示独立的剧集介绍单元;nav放导航;aside放与主体内容相关的补充信息。
这样即使把CSS全部去掉,内容的阅读顺序还是清晰可辨。我做过一个测试:把CSS暂时注释掉再看页面,语义化做得好的页面依然能看出哪里是标题、哪里是列表、哪里是正文;而全用div的页面就是一段接一段的黑色文字。读屏软件用户依赖的就是这种结构。所以每当我准备写一个区块时,会先问自己:这段内容在语义上是什么?是导航、是文章、是列表,还是仅仅为了布局而存在的容器?
3.2 一张剧集卡片的HTML写法
首页卡片我用了article作为根标签,里面再按内容分成上下两层。一个典型卡片像这样:
<article class="card"> <a href="detail-01.html"> <figure> <img src="images/cover-01.jpg" alt="《长夜灯塔》海报" loading="lazy" width="300" height="400"> <figcaption>《长夜灯塔》</figcaption> </figure> <h3>长夜灯塔</h3> <p class="meta">2024 · 悬疑 · 12集</p> <p class="rating">评分:8.6</p> </a> </article>这里有几个细节:整个卡片用a包围,意味着点击任意区域都能进入详情页,扩大点击热区;figure/figcaption在语义上表示图片及其标题,适合放海报;h3要按页面层级使用,首页在h2下出现h3,详情页里的剧名使用h1,不要多个h1。
这里补充一下标题层级的重要性。首页主标题是h2“剧集片单”,每一张卡片的剧名应该比片单层级低一级,所以是h3。如果把卡片里的剧名也写成h2,页面里就会同时出现很多个和主标题同级的标题,结构乱掉。读屏软件的用户通常依靠标题层级来快速跳转,一旦层级混乱,他们很难定位内容。
3.3 详情页的演职员表:table和dl怎么选
详情页里通常要展示导演、编剧、主演、类型、地区、语言等成对信息。第一种是用table做一张规整表格,适合有多行的数据对比;第二种是用dl(description list)做键值对,适合“名称:值”的简单列表。我当时对这两种很纠结,最后选择用table,因为导演和编剧可能有多位,可以分成几列展示。示例:
<table class="staff-table"> <caption>《长夜灯塔》基础信息</caption> <thead> <tr> <th scope="col">项目</th> <th scope="col">内容</th> </tr> </thead> <tbody> <tr> <th scope="row">导演</th> <td>某导演</td> </tr> <tr> <th scope="row">主演</th> <td>演员A、演员B</td> </tr> <tr> <th scope="row">类型</th> <td>悬疑 / 剧情</td> </tr> </tbody> </table>table适合系统化展示,dl则更轻量。具体选择标准是:如果每一项只有一行,用dl更简洁;如果数据需要横向比较,用table。后来我做分集列表时又用回了dl,因为每一集的标题和时长就是简单的“标题:时长”关系,不需要表格那样严格的行列对齐。标签没有绝对的对错,关键看内容形态。
3.4 head区别忽略:meta和title影响搜索和分享
很多初学者只关注body里的标签,忽略了head。其实head里的内容决定了页面在浏览器标签栏显示什么、在搜索结果里摘要写什么、在手机上的适应情况。我最常用的一组组合是:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="基于HTML的影剧网页实践项目,包含剧集推荐与详情展示。"> <title>11857号影剧片单 | 纯HTML实践</title> <link rel="stylesheet" href="css/style.css"> </head>其中lang="zh-CN"告诉浏览器这是一份中文页面,charset指定编码避免乱码,viewport让手机端比例正常。description虽然不影响排名权重,但会影响发布后别人分享链接时的预览摘要,值得认真写。最初我把description空着,分享到聊天里时只有光秃秃的网址;加上描述后,链接卡片会显示一段说明,看起来专业得多。
4. 让影剧页面出效果:图片、预告片和嵌入链接的正确姿势
4.1 剧照的三个来源,选错就出白屏
做影剧网页绕不开图片。剧照通常有三个来源:本地图片、外链图片、占位图。我一开始图省事,直接复制视频网站上某张海报的图片地址放进img标签,结果第二天图就裂了。原因是很多网站有防盗链机制,在外部页面引用时会被拒绝。所以后来我统一改成本地图片:保存下来的剧照都放在images文件夹,用图像处理软件转成jpg或webp格式,控制体积在200KB左右。
这里有一个比较实用的原则:如果页面是给自己练习用的,外链图片临时凑合可以;但只要准备发布或分享,就必须把图片下载到本地。除了防盗链,外链图片还有个隐患是原图如果被删除,你的页面就变成破图。本地图片虽然增加了项目体积,但稳定性最高。若只是练习没有真实剧照,可以用一个纯色div或SVG占位图放剧名,视觉效果也很整洁,还能避免版权问题。
4.2 预告片:用video标签比iframe稳
详情页加预告片是很吸引人的功能。实现方式有两种:一种是从视频站复制iframe嵌入代码;另一种是用HTML5的video标签直接播放本地MP4文件。iframe方式代码少,但是稳定性差:如果视频站调整了分享格式,或用iframe禁止了外嵌,页面就会变成一块空白。我最终选用了video标签,把预告片下载为MP4后放到video文件夹里。示例:
<video controls preload="metadata" width="640" poster="images/poster-detail-01.jpg"> <source src="video/trailer-01.mp4" type="video/mp4"> <p>你的浏览器不支持视频播放,请点击下方链接下载预告片。</p> </video>video标签的好处是播放行为完全可控。controls属性显示播放控件,preload="metadata"表示只预加载视频元数据,避免打开页面就下载全片。假如视频文件比较大,preload值还可以改成none,等用户点击播放再加载。要提醒的是,影视剧预告片涉及版权,这类页面最好只用于个人学习,不要公开发布商用。我在项目里放的是自己剪辑的测试片段,而不是影院版预告片,这也是一个合规意识。
4.3 alt和loading:两个容易被忽略的细节
图片加载失败时,alt文字会显示出来。所以alt不能是空字符串,也不能写“图片”两个字,要写清楚“《长夜灯塔》海报”这样有意义的描述,读屏软件也能读给视障用户听。另一个细节是loading="lazy",它能让页面滚动到图片附近时才真正加载图片,首页如果放了十几张剧照,可以明显缩短首屏加载时间。height和width也要写上,这样浏览器能在图片加载前预留位置,避免页面内容跳动。
我在实际测试里遇到过一种情况:图片源文件是5000像素宽的大图,直接用img展示,移动端卡了很久。后来我把图片缩到600像素以内再放进项目,页面的加载速度立刻快了不少。不要图省事直接把大图丢进页面,图片体积每减少100KB,观感都提升一个级别。
5. 多页面与导航:没有框架时怎么组织剧集目录
5.1 导航栏的语义与当前页标识
当一个影剧站有两层页面后,导航就成了必需品。我的导航栏放在header里,用nav包住一组a链接:首页、全部剧集、悬疑、科幻、关于。全部剧集就链接到首页向下滚动的位置,悬疑和科幻可以通过站内搜索功能实现,也可以用带参数的静态页面。但最简单的是先做首页和两个分类页。为了让用户知道自己在哪个页面,我在当前页对应的a标签上加了一个class="active",再配合CSS高亮。如果你不想写CSS,也可以用aria-current="page"属性标记当前页,这是标准做法。
写导航的时候,我建议给nav加一个aria-label,比如“主导航”,这样页面上如果有多个导航区域,读屏软件能区分它们。不要以为只有一两个链接就不需要nav,语义化不是做给别人看的,是让你的页面结构更规范。我后来重构项目时,把所有链接从一堆div里拎出来放进nav,CSS都不用大改,页面结构清楚了许多。
5.2 详情页跳转与“相关推荐”的写法
详情页内部,我在底部放了两个区块:一个是“上一篇/下一篇”,另一个是“相关推荐”。前者用列表包两个a,例如:
<nav class="pager" aria-label="剧集翻页"> <a href="detail-02.html">上一部:《雾港谜案》</a> <a href="detail-04.html">下一部:《雪线之上》</a> </nav>后者用aside包若干个小卡片,链接到其他详情页。这样用户看完一部剧后不用返回首页,就能自然地跳向下一部,整个浏览路径是闭合的。写多页面时,一个容易出问题的点是相对路径。如果所有html都在同一层,href直接写“detail-03.html”就可以;如果放在了子目录,需要从首页往子目录走时写“content/detail-03.html”,从子目录回首页写“../index.html”。建议先理清层级再写。
我记得第一次做相关推荐时,直接把详情页复制了六份,结果每份的“相关推荐”区块都指向固定页面,导致从A页跳到B页后,推荐列表看起来却一样,很不真实。后来我把每个详情页的推荐区块改成手动维护的3条链接,并且保证至少有一条是用户当前页面的相邻剧集,浏览体验才自然。纯静态页面就是这样,看着笨,但可控。
5.3 页内锚点:简介、演职员、预告片一键直达
详情页内容较长时,用户在顶部就能看见“简介 / 演职员 / 预告片”三个锚点链接,点击后页面滚动到对应区块。实现方法非常简单:给目标区块加上id,然后href写#id。例如:
<a href="#summary">剧情简介</a> <a href="#staff">演职员表</a> <a href="#trailer">预告片</a> ... <section id="summary">...</section> <section id="staff">...</section> <section id="trailer">...</section>要注意id必须是整个页面唯一的,不能出现两个summary。之前我复制区块时忘了改名,结果锚点永远跳到第一个区块,排查了半天才反应过来。锚点导航在纯HTML页面里非常实用,比用JavaScript做平滑滚动更轻。如果你想让滚动更丝滑,可以在CSS里加一句scroll-behavior: smooth;,不用写脚本就能实现平滑滚动效果。
6. 页面写完不等于完成:调试、校验和上线
6.1 本地预览别直接用双击,起一个本地服务
写完HTML直接用浏览器双击打开,虽然能看,但很多细节和线上环境不同。最典型的是某些浏览器对file协议下的本地视频、外链请求有限制。建议在项目目录起一个本地服务。如果你装了Python,一条命令就可以:
cd 项目目录 python3 -m http.server 8000然后浏览器访问http://localhost:8000,就能以网络协议的方式访问页面。这样可以模拟真实的线上环境,也能检查相对路径、视频加载、表单提交等逻辑。如果你不会命令行,用编辑器自带的live server插件也是一样效果。
我在这个阶段发现了一个特别隐蔽的问题:图片在本地双击打开时显示正常,但起本地服务后某些页面出现403。查了一下,是因为我把图片文件夹放在项目根目录外,本地服务只能访问项目根目录内的文件。调整目录结构后问题解决。如果你也遇到类似情况,先检查文件是不是真的在项目目录里。
6.2 最容易翻车的三个问题:乱码、路径和空白视频
我把项目发给朋友测试,反馈最多的问题是三个。
一是中文乱码。打开HTML时出现“��”这样的字符,通常是head里少了<meta charset="UTF-8">,或者保存文件时编码不是UTF-8。把这个meta放在head最前面基本能解决。
二是图片路径不对。很多人把图片放在images/文件夹里,href却写成img/xxx.jpg,或者大小写不对。建议在本地把所有文件夹、文件名统一小写字母加连字符,减少这类问题。还有一点,HTML里引用路径时用相对路径还是绝对路径要想清楚:如果准备发布到服务器根目录,路径可以写/images/cover-01.jpg;如果只是本地预览,相对路径更便携。
三是video区域白屏。常见原因是视频文件太大,还没缓冲完成,或者格式不是所有浏览器都支持。一个稳妥的做法是提供两个source,一个MP4一个WebM;如果条件有限,至少放一行文字提示用户“查看预告片的替代链接”。我在排查时还遇到过一种情况:视频文件明明在那里,但路径中带了空格,浏览器转义后找不到文件。把所有文件名中的空格改成连字符,立即解决。
6.3 把页面交给标准校验工具,再更新几处细节
上线之前,我习惯把完整的HTML代码复制到在线的HTML标准校验工具里跑一遍。这个工具会提示标签闭合错误、属性拼写错误、以及一些不该出现的废弃标签。第一次跑的时候,我的页面报了几十个警告,大多是img缺少alt、a缺少文本这类小问题。花半小时改完,页面在所有浏览器里都稳定了许多。
除此之外,还有两个细节值得做:一个是给html标签加lang="zh-CN",另一个是给页面加一个简单的“回到顶部”链接。前者不影响肉眼观看,但对搜索和可访问性有帮助;后者是我从用户角度加上的,因为详情页很长,看完预告片后想回顶部,鼠标滚轮要滚很久。我在footer里加了一个<a href="#top">回到顶部</a>,配合body顶部放一个id="top",非常轻量又实用。
6.4 后续维护的轻量思路:别让页面变成“一次性作品”
影剧信息会过时:评分可能变化,剧集状态会从连载中变成已完结。页面做完如果不维护,一个月后就过时了。我给自己的做法是:把容易变的部分放在HTML顶部注释里,每次更新时打开文件全文搜索“待更新”,就能快速定位。如果剧集增多,手动复制详情页效率太低,建议用一点JavaScript从数组或JSON文件渲染卡片列表。这一步已经超出纯HTML范围,但值得在下一篇博客里单独讲。至少,“先做出一个能跑的HTML影剧页”比“等项目完美上线再动手”更符合学习节奏。
这个编号11857的项目,后来我把它送给了同样在学前端的朋友改着玩。我们每次都从改HTML的结构开始,慢慢加一点CSS,给剧集加上评论表单,甚至加上暗色模式。回过头看,手写HTML最锻炼人的不是记住多少标签,而是学会站在用户角度考虑信息呈现的顺序。如果你也想动手试试,找一份自己想看的片单开始就行,不用等学完所有知识再开工。