
简介这份文档面向希望系统掌握 ePub 电子书制作与排版样式的读者尤其适合使用 epubBuilder 的入门与进阶制作者。内容围绕 ePub 格式的本质展开讲解其建立在 HTML 与 CSS 规范之上的结构特点并逐层梳理标签文本、属性、元素、空元素与关闭标签等核心概念同时给出 text-indent、text-align、font-size、color、font-weight 等常用排版属性的取值与用法示例帮助读者理解如何为段落、标题、链接、图片等元素声明样式从而做出更精美的电子书版式。资源包内共 1 个 doc 文档约 869KB内容以图文讲解与代码示例为主便于边看边在 epubBuilder 中实践。目前已有 946 人学习适合需要补足 ePub 排版基础、理清标签与样式对应关系的制作者参考。1. ePub 的排版和样式为什么你的电子书在阅读器里总是「长得不一样」同一份 ePub 文件在手机阅读器上段落间距正常到了平板就挤成一团封面在某个 App 里居中换个设备却偏到左上角。这不是玄学是 ePub 的排版和样式机制在作祟。ePub 本质是一个 ZIP 压缩包里面装着 XHTML 内容文档和 CSS 样式表阅读器负责解析渲染。问题在于不同阅读器对 CSS 的支持程度、默认样式覆盖策略、盒模型处理方式都不一样。你写的margin: 1em 0有的引擎老老实实执行有的直接忽略有的被用户自定义主题覆盖。所以做 ePub 排版核心不是「写好看的 CSS」而是「写能被各种阅读引擎稳定解析的 CSS」。这篇文章面向需要自己动手做电子书排版的开发者、编辑和技术出版从业者从文件结构讲到样式调试把可复现的流程和踩过的坑一次说清。2. 拆开 ePub内容文档和样式表到底怎么组织2.1 一个最小 ePub 的文件结构ePub 规范要求包内至少包含几个关键文件mimetype必须是第一个文件且不压缩、META-INF/container.xml告诉阅读器去哪里找 OPF 文件、.opf文件元数据和清单、以及实际的 XHTML 内容文档和 CSS。下面是一个典型的最小结构mypublication.epub ├── mimetype ├── META-INF/ │ └── container.xml ├── OEBPS/ │ ├── content.opf │ ├── nav.xhtml │ ├── styles/ │ │ └── main.css │ └── text/ │ ├── chapter01.xhtml │ └── chapter02.xhtmlmimetype文件内容只有一行application/epubzip不能有换行符之外的任何多余字符且打包时必须第一个写入、不压缩。这是很多新手打包后阅读器打不开的第一大原因。container.xml的作用是声明 OPF 文件的位置?xml version1.0 encodingUTF-8? container version1.0 xmlnsurn:oasis:names:tc:opendocument:xmlns:container rootfiles rootfile full-pathOEBPS/content.opf media-typeapplication/oebps-packagexml/ /rootfiles /containerfull-path是相对于 ePub 根目录的路径写错了阅读器就找不到清单文件直接报错。2.2 OPF 文件里必须写对的三件事OPF 文件是 ePub 的「黑匣子」入口它定义了元数据、文件清单和阅读顺序。以下是最小可用示例?xml version1.0 encodingUTF-8? package xmlnshttp://www.idpf.org/2007/opf version3.0 unique-identifierpub-id metadata xmlns:dchttp://purl.org/dc/elements/1.1/ dc:identifier idpub-idurn:uuid:12345678-1234-1234-1234-123456789abc/dc:identifier dc:title示例出版物/dc:title dc:languagezh-CN/dc:language meta propertydcterms:modified2025-01-01T00:00:00Z/meta /metadata manifest item idnav hrefnav.xhtml media-typeapplication/xhtmlxml propertiesnav/ item idcss-main hrefstyles/main.css media-typetext/css/ item idch01 hreftext/chapter01.xhtml media-typeapplication/xhtmlxml/ item idch02 hreftext/chapter02.xhtml media-typeapplication/xhtmlxml/ /manifest spine itemref idrefch01/ itemref idrefch02/ /spine /package三个关键点dc:identifier必须是唯一标识通常用 UUIDdcterms:modified在 ePub 3 中是必填项格式必须是 UTC 时间manifest里每个文件都要列出来漏掉 CSS 文件会导致样式完全不生效。spine的itemref顺序决定阅读顺序idref必须和manifest里的id对应。2.3 XHTML 内容文档的写法约束ePub 3 的内容文档必须是合法的 XHTML这意味着所有标签必须闭合属性值必须加引号必须转义为amp;。常见翻车场景是直接从 Word 或网页复制内容里面带着未闭合的br或img标签打包后阅读器直接白屏。?xml version1.0 encodingUTF-8? !DOCTYPE html html xmlnshttp://www.w3.org/1999/xhtml xmlns:epubhttp://www.idpf.org/2007/ops xml:langzh-CN langzh-CN head meta charsetUTF-8/ title第一章/title link relstylesheet typetext/css href../styles/main.css/ /head body section epub:typechapter h1第一章 标题/h1 p正文段落内容。/p /section /body /htmlepub:typechapter是语义化标注帮助阅读器理解内容结构但不是所有阅读器都会用到。link标签的href路径是相对于当前 XHTML 文件的写错路径样式就加载不到。3. 样式表怎么写才能让多数阅读器买账3.1 从零写一份可用的基础 CSSePub 的 CSS 和网页 CSS 最大的区别是你没有浏览器 DevTools 可以实时调试而且阅读器会注入自己的默认样式。所以策略是「显式声明、避免依赖继承、不碰阅读器保留属性」。下面是一份经过多设备验证的基础样式/* 基础重置只重置必要的不要全局 reset */ body { margin: 0; padding: 0; line-height: 1.6; font-family: serif; /* 不指定 font-size让阅读器控制 */ } /* 段落用 em 而非 px保证缩放一致性 */ p { margin: 0; text-indent: 2em; line-height: 1.6; } /* 标题避免使用阅读器可能覆盖的简写属性 */ h1 { font-size: 1.5em; margin-top: 1.5em; margin-bottom: 0.8em; text-indent: 0; page-break-before: always; } h2 { font-size: 1.3em; margin-top: 1.2em; margin-bottom: 0.6em; text-indent: 0; } /* 图片限制最大宽度防止溢出 */ img { max-width: 100%; height: auto; } /* 避免使用 position: fixed/absolute多数阅读器不支持 */几个关键决策font-size不写绝对值用em或百分比因为阅读器允许用户调整字号写死16px会破坏这个功能。text-indent: 2em是中文排版惯例但注意标题和图片说明要重置为 0。page-break-before: always让每章从新页开始但有些阅读器用break-before: page两个都写上更保险。3.2 阅读器兼容性哪些 CSS 属性是雷区不同阅读引擎对 CSS 的支持差异很大。根据实际测试经验以下属性在多数阅读器上表现不稳定CSS 属性兼容情况建议position: fixed几乎全部不支持完全避免float部分支持行为不一致图片排版用text-align替代flexbox老设备不支持仅用于简单居中提供降级grid多数不支持避免vh / vw部分支持用em / %替代rem部分老引擎不支持用em替代media支持但断点行为不同谨慎使用只做字号微调font-face支持但字体嵌入有坑见 3.3 节最稳妥的做法是只用margin、padding、font-size、line-height、text-align、text-indent、color、background-color、border这些基础属性。复杂布局用嵌套div加text-align和margin来实现。3.3 字体嵌入什么时候值得做什么时候放弃嵌入自定义字体可以让排版更可控但代价是文件体积增大而且部分阅读器会忽略嵌入字体、强制使用用户设定字体。如果确实需要嵌入font-face { font-family: CustomSerif; src: url(../fonts/custom-serif.woff2) format(woff2), url(../fonts/custom-serif.woff) format(woff); font-weight: normal; font-style: normal; font-display: swap; } body { font-family: CustomSerif, serif; }字体文件必须加入 OPF 的manifest否则不会被包含在 ePub 包内。font-display: swap让文字先用系统字体渲染字体加载后再替换避免白屏。但注意如果阅读器不支持font-display这个属性会被忽略不影响基本功能。我一般只在正文需要特殊字体比如古籍排版需要楷体时才嵌入普通小说和文档直接用serif或sans-serif让阅读器自己决定兼容性最好。4. 打包、验证和调试从文件夹到可分发 ePub4.1 用命令行打包并确保 mimetype 正确打包 ePub 最容易翻车的地方就是mimetype的压缩问题。用zip命令的正确姿势# 进入 ePub 源文件目录 cd mypublication # 第一步只打包 mimetype不压缩必须第一个写入 zip -X0 ../output.epub mimetype # 第二步追加其余文件使用压缩 zip -Xr9D ../output.epub META-INF OEBPS # 验证 mimetype 是否未压缩 unzip -l ../output.epub | head -5-X去掉额外文件属性-0表示不压缩-r递归-9最高压缩率-D不写入目录条目。如果顺序反了或者mimetype被压缩了部分阅读器会直接拒绝打开。4.2 用 epubcheck 做结构验证打包完成后用 epubcheck 做一次结构校验能提前发现大部分低级错误# 下载 epubcheck 后解压运行校验 java -jar epubcheck-5.1.0/epubcheck.jar output.epub # 输出示例 # Validating against EPUB version 3.0 # No errors or warnings detected.如果报OPF-003错误通常是manifest里缺少文件引用报RSC-005通常是 XHTML 语法错误报CSS-008通常是 CSS 属性值不合法。每次修改后都跑一遍比在阅读器里反复试快得多。4.3 多阅读器交叉验证的实操方法结构校验通过不代表渲染效果一致。我一般会在至少三个不同引擎的阅读器上做交叉验证一个基于 WebKit 的、一个基于 Blink 的、一个原生渲染的。重点检查四个位置段落缩进是否一致、标题分页是否生效、图片是否溢出、目录跳转是否正常。如果发现某个阅读器上样式异常先用「最小复现」法定位把出问题的那个 XHTML 文件和 CSS 单独打包成一个最小 ePub逐步删减样式规则直到找到触发问题的具体属性。这个过程比盲猜快得多。5. 避坑ePub 排版里最容易翻车的五个地方现象一打包后阅读器提示「文件损坏」或直接闪退。原因mimetype被压缩了或者不是包内第一个文件。 解决用zip -X0单独写入mimetype再用zip -Xr9D追加其余文件。打包后务必用unzip -l确认mimetype的压缩方式是Stored而非Deflateg。现象二CSS 文件明明写了阅读器里完全没生效。原因OPF 的manifest里漏掉了 CSS 文件或者 XHTML 里link的href路径写错。 解决检查manifest中是否有item idcss-main hrefstyles/main.css media-typetext/css/再检查 XHTML 中href是否相对于当前文件正确。路径大小写也要注意部分阅读器区分大小写。现象三段落缩进在某个阅读器上变成了 0或者变成了巨大间距。原因阅读器注入了自己的默认p样式覆盖了你的text-indent。或者你用了px单位阅读器缩放时行为异常。 解决用em而非px并且在p选择器上显式写text-indent: 2em。如果仍然被覆盖尝试提高选择器优先级比如body p { text-indent: 2em; }。现象四嵌入字体后文件体积暴涨但阅读器里字体没变化。原因字体文件本身很大中文字体动辄几 MB且部分阅读器忽略嵌入字体。 解决用字体子集化工具只保留用到的字符中文字体子集化后通常能压到几百 KB。如果目标阅读器明确不支持嵌入字体直接放弃用系统字体栈font-family: Songti SC, SimSun, serif;做降级。现象五目录能显示但点击不跳转。原因nav.xhtml里的href锚点与 XHTML 中的id不匹配或者spine里没有包含对应文档。 解决检查nav.xhtml中每个a hreftext/chapter01.xhtml#sec1对应的文件里是否有idsec1的元素。ePub 3 的导航文档必须用nav epub:typetoc包裹。6. 进阶用 CSS 变量和媒体查询做自适应排版ePub 3 支持 CSS 自定义属性变量这给多设备适配提供了新思路。虽然老阅读器不支持但新引擎基于 Chromium 的阅读器、Apple Books 等已经可以正常解析。我一般会写一套带降级的方案/* 降级先写死默认值 */ body { font-size: 1em; line-height: 1.6; margin: 0 5%; } /* 支持变量的阅读器会覆盖上面的值 */ :root { --body-font-size: 1em; --body-line-height: 1.6; --body-margin: 5%; } body { font-size: var(--body-font-size, 1em); line-height: var(--body-line-height, 1.6); margin: 0 var(--body-margin, 5%); } /* 大屏设备微调 */ media screen and (min-width: 600px) { :root { --body-margin: 10%; } }这个方案的核心逻辑是先写一份所有阅读器都能解析的基础样式再用变量和媒体查询做增强。不支持变量的阅读器会忽略var()声明回退到前一条规则支持变量的阅读器会应用新值。媒体查询同理不支持的引擎直接跳过。验证方法很简单在目标阅读器里打开调整系统字号观察段落间距和边距是否按比例变化。如果字号变大但边距没变说明margin用了固定单位需要改成百分比或em。还有一个实用技巧用page-break-inside: avoid防止图片和代码块被分页截断。这个属性在多数阅读器上有效但注意不要用在长段落上否则可能导致大片空白。img, pre, blockquote { page-break-inside: avoid; }最后说一个血泪教训每次改完 CSS不要只在一个阅读器上看效果。我曾经因为只在手机上看没问题就发布了结果有读者反馈在某个平板阅读器上整个排版全乱——原因是那个阅读器不支持em单位的text-indent只认px。后来我养成了一个习惯任何样式规则只要涉及单位就在至少两个不同引擎上各测一遍。这个习惯帮我省掉了大量售后沟通。希望帮到你。本文还有配套的精品资源点击获取