☰
用HTML写简历:从结构搭建到打印PDF的完整实践指南
2026/10/17 5:48:51 网站建设 项目流程

最近有朋友找我改简历,他在文档排版软件里调了快一下午,导出之后字体忽大忽小,列表缩进对不齐,最后一栏内容还被截掉一截。我让他把内容原样给我,然后新建了一个HTML文件,半小时后交回去一份打印出来不变形、看着很清爽的简历。他一直以为HTML简历是技术圈人才会玩的东西,其实它就是一份网页文件,只是把简历内容用网页的方式去描述和排版而已。

这篇文章把我做HTML简历的完整思路写下来:从简历内容怎么拆模块、结构怎么搭、样式怎么调,到打印和导出PDF时那些最容易翻车的细节,一条条说清楚。不管你是程序员,还是只写过一点网页的新手,照着这套思路都能做出一份拿得出手的个人简历。

1. 为什么放着现成的排版软件不用,偏要用HTML写简历

先说个反直觉的结论:用HTML写简历,不是技术在炫技,而是它刚好解决了简历排版中最常见的“失控感”。

在所见即所得的文档工具里,你看到的效果和最终打印出来的效果之间,总会隔着一层“魔法”。明明屏幕上对齐了,换个版本导出又错位;默认字体、自动编号、粘贴时的格式残留,会在你完全没注意的地方悄悄搞事。HTML恰恰相反,每一个像素、每一条间距都是代码里明确写死的,没有默认干扰,也没有隐形的格式继承。

1.1 简历排版的最大痛点,其实是“失控”

你可以回想一下被文档工具支配的经历:一段从旧文档里粘贴过来的内容,把整个段落样式带乱;标题字号不小心用了某个内嵌模板,换台电脑就整体变掉;导出PDF时某一页莫名其妙多出半行空白。这些问题的本质都是同一件事——你并没有真正控制这份文档。

HTML写简历时,同样的场景完全不同。文件的呈现由浏览器解析HTML和CSS决定,而这些都是纯文本代码。字号是多少就是多少,行距是多少就是多少,浏览器不会好心替你“自动修正”。我把这种掌控感叫作“所见即所得之上的另一层确定性”:你在代码里看到的,和打印出来的,是同一套逻辑。

1.2 代码化简历的三个实际好处

第一,方便版本管理。简历要改是很频繁的事,投不同岗位可能要微调经历顺序,突出不同技能。HTML文件是纯文本,放进任何版本管理工具都能保留每次改动的过程,出问题了随时回退。

第二,一份代码多处使用。同一个HTML文件可以本地打印,可以右键另存为PDF,可以放到某个静态托管平台变成在线简历链接,甚至可以复制到邮件正文里直接发。换一套CSS,白色简历能变成深色主题,不用重写内容。

第三,排版能力非常精确。两栏布局、工作时间右对齐、技能标签横排、页脚固定,这些都是HTML和CSS的“日常操作”,在传统文档工具里反而是要折腾半天的东西。

1.3 适合谁来掌握

写HTML简历这件事,门槛其实比想象中低。你不需要懂JavaScript,不需要会任何框架,只要能理解几个标签和一小段CSS就够。我见过不少非技术背景的求职者,用这套方法做出了比模板简历精致得多的效果。所以这篇文章的目标读者很简单:想让简历排版更可控、更专业的人,无论基础如何,都可以往下看。

2. 让简历内容先于样式:模块划分与信息排序

很多初学者一上来就盯着样式,纠结配色和字体,结果内容结构一团乱。我的习惯是先完全不想样式,只把简历当一篇结构化的文章来拆解。内容模块定清楚了,后面写HTML和CSS都顺很多。

2.1 简历内容由哪些模块构成

一份常见的中文简历,基本逃不出这几块:

模块内容HTML对应建议
个人信息姓名、电话、邮箱、所在地header / 联系人间距
求职意向目标岗位、期望城市、薪资范围简短段落
教育经历学校、专业、学位、时间段结构化列表
工作经历公司、岗位、职责、业绩条目列表
项目经历项目名称、角色、技术点、结果条目列表
技能清单技术栈或核心能力标签列表

是不是感觉这些模块之间差异很大?这就是先用HTML语义化去划分它们的原因:教育经历和工作经历天然是“列表型条目”,技能手机天然是“标签型条目”,把它们放到合适的标签里,后面排版会省很多事。

2.2 信息排序的优先级原则与篇幅分配

简历不是自传,阅读者希望在最快时间内看到你最有价值的信息。根据我个人经验,排序原则就一句话:用“相关性和时间线”做双重排序。

  • 求职场次优先于学历:如果是社招简历,工作经历应该排在教育经历前面;应届简历则教育经历在前。
  • 时间都是倒序:最近的经历放最前面。
  • 篇幅按“目标岗位的匹配度”分配:一段过往经历如果和求职岗位强相关,多写几行;弱相关,点到为止,甚至可以直接不写。

字体篇幅上也给个参考:一页纸简历适合应届生和三五年经验内的人,两部分经历内容控制在4个条目以内;资产较丰富、有大量项目成果的人可以自然延伸到两页,但不要为了撑页面而把不重要的经历灌进去。

2.3 一个实用的内容检查思路

写完模块后,我建议做一个“30秒速读测试”。让一个不熟悉你情况的人只扫一眼你的简历,看能不能在30秒内说出你以前在什么行业、做过什么类型的岗位、有哪些核心技能。如果不能,说明信息排序还是有问题,赶紧调整。这个测试做完之前不要碰任何样式。

3. 别急着写样式:先用语义化标签把骨架搭稳

我见过太多简历HTML是把整页内容堆在一堆无意义的div里,后续想要打印优化或做样式调整,就变得非常痛苦。HTML里那些看起来“只是不同名字的盒子”的标签,其实各自有各自的含义,用对了会让整个页面结构清晰很多。

3.1 为什么简历和网页一样需要语义化

语义化标签的好处有两层。一层是给浏览器理解的:header、main、section这些标签让网页结构更清楚,屏幕阅读器能更好地把内容朗读给视障用户。另一层是给你自己理解的:三个月后再打开这份代码,看到<section class="work-experience">,立刻知道这一块是工作经历,不用根据内容反推。

简历篇幅很短,不一定需要<footer>这种元素,但main、section、header这三个非常值得用。它们对应的就是一种很自然的简历结构:main是整份简历,header是姓名和联系方式,section是每个大模块。

3.2 常用标签在简历里的具体用法

拿一份简历从头到尾看:

  • h1只保留给姓名。不要滥用,整份简历只有一个大标题。
  • h2用作每个模块的小标题,比如“教育背景”“工作经历”“项目经历”。
  • h3用来做每条经历的岗位名称或项目名称。
  • 联系方式的电话、邮箱、地址,用ul列表而不是用一串文本硬拼,这样后面做间距和换行都方便。
  • 技能标签、项目里的一句话说明,都可以用ul li表达。

很多人会问,为什么不用table两列排开?表格在语义上适合展示关系型数据,而简历里的工作经历、时间、岗位之间不是表格关系,用列表反而更容易控制。

3.3 全局样式的重置与基础设置

浏览器自带默认样式,比如body会有8px的外边距,h1到h6自带不同的字号和粗细,ul自带项目符号和左内边距。这些默认值如果不处理,简历就会显得“原生态”。所以在CSS第一行,我会先做一次简单的全局重置:

* { margin: 0; padding: 0; box-sizing: border-box; }

然后给整个页面设置基础样式,相当于给“地基”定了标准:

body { font-family: "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif; font-size: 14px; line-height: 1.6; color: #333333; background: #f2f2f2; }

这段基础样式看着简单,但影响非常大:字号统一了,行距统一了,颜色统一了,页面背景和简历卡片背景分开了。后面所有精细调整都在这套基础上进行。

4. 排版细节一次讲清:字体、间距、配色与两栏布局

骨架有了,接下来是让简历“看起来专业”的排版段。这里我先把话说在前头:简历排版好看与否,80%取决于字体、间距和留白,而不是花哨的边框和背景色。

4.1 字体系统的选择

中文字体有一个比较麻烦的特点:不同操作系统默认自带的中文不同,所以不要指望写一个字体名就能在所有人电脑上一致显示。我的做法是用一个字体栈,把它放在body上:

font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif;

这个字体栈的意思是从左到右尝试:新的苹果系统用苹方,Windows用微软雅黑,Linux通常装有思源黑体,实在都没有就回退到无衬线字体。实际打印时,只要本机有其中一种,就能正常显示。

字号方面,我的经验值是这样:姓名用26px到28px,模块标题用16px,正文内容用14px,次要信息比如时间、地点、联系方式用13px。简历最忌讳正文字号超过15px,否则一眼看上去就像文档编辑器的默认大字。

4.2 间距系统与行高的拿捏

间距是简历版式里最容易被忽视,也最决定成败的因素。我自己有一个简单的间距体系:

  • 模块与模块之间:24px到32px
  • 模块标题与内容之间:14px到18px
  • 单个经历条目之间:14px到16px
  • 条目的标题行与补充说明之间:4px到6px

行高保持1.5到1.6比较舒适,太紧会挤,太松会浪费空间。有一个很实用的技巧:同一份简历里,间距的值最好都能被4整除,比如16、20、24、28、32,这样垂直方向看过去会非常规律。

4.3 颜色搭配的克制原则

简历不是海报,内容为王,颜色只是辅助。我通常只用三个层次的色值:

  • 标题和关键信息:接近黑色,比如#222
  • 正文内容:深灰色,比如#444
  • 辅助信息:更浅的灰色,比如#777

除此之外,只选一个强调色,用在姓名、模块标题下划线或技能标签上。强调色不要是那种非常艳丽的荧光色,成熟的蓝色系是大多数人的安全选择。三色体系的好处是:打印成黑白后依然层次分明,不会因为去掉颜色就变成一团灰。

4.4 两栏布局的flex和grid实现

布局层面,中文简历最常见的方案是两栏:左边窄栏放技能、教育等偏静态的信息,右边宽栏放工作经历和项目。用CSS的Grid布局来做这件事非常干净:

.resume-body { display: grid; grid-template-columns: 240px 1fr; gap: 24px 36px; }

把整个简历主体的内容分成左右两列,左边固定240px宽,右边占剩下的全部空间。这就是“窄栏放辅助信息,宽栏放核心经历”的经典结构。

需要特别注意的一个问题:我会在打印样式里把两栏临时改回一栏。原因后面会细讲,这里先记下这个思路。如果你不希望简历在纸上变成两栏,可以跳过这个布局方案,直接全部用单栏,结构也非常适合简历这种线性阅读场景。

5. 打印优化:HTML简历到底行不行,打印说话

经常有人问:在网页上做得挺好看,打印出来怎么这么丑?实话实说,大多数问题都出在没做打印样式适配。浏览器在打印网页时有一套和屏幕完全不同的规则,你必须在CSS里专门告诉它打印时怎么排。

5.1 用@media print做一套专属打印样式

CSS里的@media print就是专门为打印准备的媒体查询。凡是写在里面的样式,只在打印和导出PDF时生效。下面这套是我每次做简历都会加上的基础:

@media print { body { background: #ffffff; } .resume { box-shadow: none; margin: 0; padding: 0; } .resume-body { display: block; } }

第一行把页面底色改成纯白,避免打印时大块背景色浪费墨水;第三行把屏幕上的卡片阴影去掉;第五行是关键,让两栏布局在打印时变回单栏,这样阅读顺序就和人的自然阅读顺序一致了。

5.2 分页与打印区域的控制

简历打印最尴尬的瞬间是什么?一段经历的上半部分在第一页,下半部分跑到第二页;或者模块标题留在上一页底部,内容却从下一页开始。这两个问题都有对应CSS属性:

section, .resume-item { break-inside: avoid; }

break-inside: avoid的作用是告诉浏览器:这个元素的内容尽量保持完整,不要被分页截断。简历里每个经历条目、每个模块都应该加上这条规则。

控制整份简历占一页纸,除了内容本身要精简,也可以用@page设置打印页边距:

@page { size: A4; margin: 12mm 10mm; }

上面这段的意思是:打印页默认A4纸张,上下留12毫米边距,左右留10毫米边距。不同打印机的可打印区域不一样,如果你发现内容贴着纸边缘,可以适当调大这两个值。

5.3 打印导出PDF时的实操顺序

这部分不少人问过,我直接写成步骤:

  1. 用系统自带或任意的现代浏览器打开HTML文件。
  2. 按打印快捷键(通常是Ctrl+P或对应系统快捷键)。
  3. 在打印预览里,如果看不到背景色,记得勾选“背景图形”相关选项。
  4. 目标打印机选择“另存为PDF”。
  5. 检查预览里是否有元素被分页截断,有就回代码里调整间距或补break-inside。

整个流程下来,收获的其实不是一份PDF文件,而是一份在任何电脑上打开都一样稳定显示的简历版本。

6. 一份可直接复用修改的HTML简历完整代码

前面几章讲了理论和思路,这一节给一份可以直接动手的完整骨架。代码里包含姓名信息、技能标签、两栏布局、打印样式,一段一注释。

6.1 代码总览:HTML与CSS写在同一个文件里

为了方便演示和直接复制使用,我把CSS放在<style>标签内、写在HTML文件的头部,这样一份文件就能独立工作,双击就能在浏览器里打开。

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>个人简历 - 王小明</title> <style> /* ---------- 基础重置 ---------- */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif; font-size: 14px; line-height: 1.6; color: #333333; background: #f0f0f0; } /* ---------- 简历主体卡片 ---------- */ .resume { max-width: 794px; /* 约A4纸宽度 */ margin: 32px auto; background: #ffffff; padding: 40px 44px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08); } /* ---------- 头部:姓名与联系方式 ---------- */ .resume-header { border-bottom: 2px solid #222; padding-bottom: 18px; margin-bottom: 26px; } .resume-header h1 { font-size: 28px; letter-spacing: 3px; } .contact-list { list-style: none; display: flex; flex-wrap: wrap; gap: 8px 28px; margin-top: 12px; color: #666666; font-size: 13px; } /* ---------- 主体两栏布局 ---------- */ .resume-body { display: grid; grid-template-columns: 230px 1fr; gap: 20px 32px; } /* ---------- 通用模块标题 ---------- */ .module-title { font-size: 17px; font-weight: 600; border-bottom: 1px solid #e0e0e0; padding-bottom: 6px; margin-bottom: 14px; letter-spacing: 1px; } /* ---------- 侧栏:技能与教育 ---------- */ .sidebar section { margin-bottom: 24px; } .skill-list { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; } .skill-list li { background: #f5f7fa; padding: 3px 10px; border-radius: 4px; font-size: 13px; } .edu-item { margin-bottom: 14px; } .edu-item p { color: #666666; font-size: 13px; } /* ---------- 主栏:工作与项目经历 ---------- */ .experience-item { margin-bottom: 22px; break-inside: avoid; } .item-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; } .item-head h3 { font-size: 15px; font-weight: 600; } .item-meta { color: #888888; font-size: 12px; white-space: nowrap; } .item-desc { margin-top: 6px; color: #444444; font-size: 13px; } .item-desc li { margin-left: 18px; margin-bottom: 4px; } /* ---------- 打印样式 ---------- */ @media print { body { background: #ffffff; } .resume { max-width: none; margin: 0; padding: 0; box-shadow: none; } /* 打印时两栏变单栏 */ .resume-body { display: block; } .skills-wrap { margin-bottom: 20px; } /* 链接不要显示长串网址 */ a { text-decoration: none; color: #222222; } /* 每个模块保持完整,不被分页切断 */ .experience-item { break-inside: avoid; } } @page { size: A4; margin: 12mm 10mm; } </style> </head> <body> <main class="resume"> <!-- 头部:姓名与联系方式 --> <header class="resume-header"> <h1>王小明</h1> <ul class="contact-list"> <li>电话:138xxxx1234</li> <li>邮箱:xiaoming@example.com</li> <li>所在城市:某市</li> <li>个人主页:example.com</li> </ul> </header> <div class="resume-body"> <!-- 左侧窄栏 --> <aside class="sidebar"> <section> <h2 class="module-title">技能</h2> <ul class="skill-list"> <li>HTML / CSS</li> <li>JavaScript</li> <li>数据分析</li> <li>项目管理</li> </ul> </section> <section> <h2 class="module-title">教育经历</h2> <div class="edu-item"> <h3>某高校</h3> <p>计算机科学与技术 · 本科</p> <p>2020.09 - 2024.06</p> </div> </section> </aside> <!-- 右侧主栏 --> <main class="content"> <section> <h2 class="module-title">工作经历</h2> <div class="experience-item"> <div class="item-head"> <h3>某科技有限公司 · 前端开发工程师</h3> <span class="item-meta">2024.07 - 至今</span> </div> <ul class="item-desc"> <li>负责公司后台管理系统的页面开发与重构,页面打开速度提升约30%。</li> <li>参与某个跨平台项目的组件库建设,沉淀通用组件12个。</li> </ul> </div> </section> <section> <h2 class="module-title">项目经历</h2> <div class="experience-item"> <div class="item-head"> <h3>某电商数据分析平台</h3> <span class="item-meta">2024.01 - 2024.06</span> </div> <ul class="item-desc"> <li>搭建报表页面和可视化模块,日均处理订单数据约5万条。</li> <li>制定前端代码规范,建立组件复用检查机制。</li> </ul> </div> </section> </main> </div> </main> </body> </html>

6.2 这份代码里值得细看的三处设计

第一处是.item-head的display: flex; justify-content: space-between。这一小段把所有经历的标题左侧靠左、右侧时间靠右,中间距离自动拉开。相比用表格模拟或者手动挤空格,这种方式对齐稳定得多,也是整个简历里最常用到的功能之一。

第二处是打印时的.resume-body { display: block; }。这会让两栏变一栏,阅读顺序变成:个人信息、技能、教育、工作经历、项目经历。虽然少了视觉上的左右分栏,但打印出来非常稳妥,特别是过简历筛选工具时,单栏的线性文本更容易被准确提取。这也是一份简历在“美观”和“实用”之间最值得妥协的地方。

第三处是break-inside: avoid写在.experience-item上。它能防止某个经历条目被分页切断,避免出现第一页结尾只有半行字的尴尬。

6.3 调试和替换的小方法

代码里所有内容都是虚构的示例,你只需把文字替换成真实信息,动手按自己的情况删减模块。我建议把过程放在本地浏览器里实时预览,改一个属性保存后刷新,马上能看到效果。为了避免样式越改越乱,每改一个重要参数之前先在注释里写下意图,不然隔几天再看,会忘了当时为什么这么设。

7. 写HTML简历这些年踩过的坑

最后聊几个我实际使用中遇到过的问题。这些问题不算多严重,但一旦中招就很影响体验,知道原因后都很容易绕开。

7.1 第一个坑:打开文件乱码

刚用HTML写简历那会儿,我用系统自带的文本工具新建文件,写完在浏览器打开全是乱码。原因就是文件编码和HTML声明不一致。解决办法很固定:在<head>里写<meta charset="UTF-8">,并且保存文件时选UTF-8编码。如果这两者不一致,浏览器就会按自己的猜测去解码。

7.2 第二个坑:打印后背景色悄悄消失

网页上技能标签的浅蓝背景很好看,打印出来却变成灰底甚至白底。不是因为打印机省墨,而是浏览器打印默认不渲染背景色。如果你必须保留背景色,可以在打印样式中加一行:

* { -webkit-print-color-adjust: exact; print-color-adjust: exact; }

不过我个人的建议是,简历本身尽量别依赖背景色,黑白打印时不加颜色依然能分清层级,才是最稳的。

7.3 第三个坑:字体排版在不同电脑上不一致

同一份HTML,在Windows和苹果系统上打开,字间距、行宽可能都不一样。这里多半是字体渲染差异造成的。解决办法就是前面说的那套字体栈,让每个系统优先加载自己最擅长的中文字体;同时保持正文字号采用固定像素值,不要用相对单位加水。打印PDF最好在你自己常用的一台电脑上完成,这样能确保最终交付版和你的预期一致。

7.4 第四个坑:两栏布局用float或定位来实现

虽然旧的CSS方案也能排版,但用float或者绝对定位做两栏简历,打印时极其容易错位。特别是当你给内容加了break-inside: avoid之后,浮动元素的分页行为在不同浏览器里差异很大。我统一改用Grid或Flexbox之后,这类问题基本没再出现过。新写简历的人,没必要再回头踩老技术的坑。

7.5 第五个坑:往简历里堆链接留下长串网址

简历里附加个人主页或作品链接时,如果链接本身很长,打印出来后会在页面上显示一串带下划线的网址,非常影响美观。处理方式是把链接文字写得短一点,比如“个人主页”四个字,然后在打印样式里把color改回黑色、去掉下划线。前面代码里已经给了对应片段,实际操作起来效果立竿见影。


最后再分享一个小习惯:我每次写完简历,都会顺手在底部加一个CSS变量定义强调色,比如把模块标题的边框色、姓名颜色都指向同一个变量。这样后来想换主题时,只要改一处,整份简历就跟着变了。写HTML简历这件事,一旦把骨架和样式分开想清楚,后续每一次调整都会变得越来越快。

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

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

立即咨询