写中文文档这件事,听起来像是"把字打进去、调调字体"的活儿,真上手才会发现坑比想象的多。有人是为了交毕业论文,有人是要整理一份技术手册,也有人只是想给自己维护的开源项目补一份像样的中文说明——不管你平时翻的是哪个库的中文文档,轮到自己产出一份中文文档的时候,排版这关总得正面过一遍。我用 Overleaf 写中文材料断断续续有几年了,从最早的课程论文、实验室报告,到后来的产品说明书和内部规范手册,中间踩过的编译报错、字体缺失、引用乱码、封面错位,摞起来能写满好几页纸。这篇就把我自己这套流程完整摊开讲一遍:从建项目、选编译器、配字体,到插图片、排表格、挂参考文献,再到多人协作和修订模式,最后是那堆让人头大的报错到底怎么查。适合刚接触 LaTeX 的新手,也适合用过英文模板但一换成中文就懵的老用户。全程不玩虚的,能给配置就直接给配置。
1. 先搞清楚中文文档到底卡在哪几个点
1.1 一个很常见的误解
很多人第一次用 LaTeX 写中文,会默认"中文就是换了个字符集",于是拿一份英文模板,把\usepackage[utf8]{inputenc}一加,直接开写。结果编译出来的东西要么一片空白,要么满屏方框,要么干脆报Missing character的警告。这不是操作水平问题,而是底层机制决定的。
LaTeX 最早的设计里,排字依赖的是"字体编码"这套体系,它假设每个字符宽度一致、断行规则一致。英文单词靠空格断行,字符宽度基本固定;中文没有空格、每行要均匀撑满、标点还要处理前后挤压。这套规则跟原始 TeX 的假设完全不同。所以中文排版在很长一段时间里是靠一套叫 CJK 的宏包硬撑的,配置繁琐、字体难找,问题多到劝退。
后来出现了 XeTeX 引擎配合 xeCJK 宏包,情况才彻底变了。它直接调用系统里现成的字体文件,不再需要把字体转成 TeX 能认的特殊格式,中文排版的复杂度一下从"折腾一天"降到"两行配置"。Overleaf 上真正好用的中文方案,基本都建立在这条路线上。理解了这一点,后面所有的选择就都有了依据。
1.2 Overleaf 在中文场景下真正省掉的三件事
第一件是环境。本地装 TeX Live 再配中文字体,是新手最容易卡住的地方:字体路径不对、宏包版本不匹配、系统字体名和 LaTeX 里写的不一致,每种都能耗掉半个工作日。Overleaf 把 TeX Live 和一整套开源中文字体(比如 Fandol 系列)预装好了,项目建起来就能直接调用,不用管路径也不用管版本。
第二件是协作成本。中文文档往往不是一个人写的,尤其是规范手册、项目报告这类东西,三五个人的意见要合到一起。传统做法是各自改各自的 Word,最后人工合并,格式还原全靠运气。Overleaf 的在线协作让所有人改的是同一份源码,冲突能即时看到,谁改的什么时候改的一目了然。
第三件是排版一致性。中文文档里最烦人的几个东西——目录页码、章节编号、图表编号、参考文献格式——用 LaTeX 都是自动生成的,你改动正文之后重新编译,所有编号和目录会自动对齐。这一点在章节动辄二三十个的长文档里,价值特别明显。
注意:Overleaf 的免费方案在协作人数和编译时长上有额度限制,写长文档时编译排队会比较明显。如果项目很大,建议在动手前先确认一下当前方案的限制,避免写到一半被卡住。
2. 动手前的三个关键选择,选错后面全是返工
2.1 编译器:为什么几乎无脑选 XeLaTeX
Overleaf 的项目菜单里能选编译器,常见的有 pdfLaTeX、XeLaTeX、LuaLaTeX 三种。写中文我建议直接锁定 XeLaTeX,理由有三条。
一是字体调用方式最省事。XeLaTeX 可以直接用\setCJKmainfont{}这种写法指定中文正文字体,填的是字体名而不是路径;pdfLaTeX 要配 CJK 宏包,还得准备特定编码的字体包,配置量翻几倍。
二是图片格式兼容性好。XeLaTeX 和 pdfLaTeX 一样能直接吃 png、jpg、pdf 三种主流格式,不用中途转换;有些老流程要求 eps,反而多一道手续。
三是中文断行和标点处理成熟。xeCJK 宏包在 XeLaTeX 下是原生支持的,标点挤压、避头尾、字间距这些细节都有默认合理值,不需要你手动调。
LuaLaTeX 也是可行选项,功能上甚至更灵活,能写 Lua 脚本干预排版。但它在 Overleaf 上的首次编译速度通常比 XeLaTeX 慢一些,除非你有特殊的自动化需求,否则没必要舍近求远。
| 编译器 | 中文支持方式 | 字体调用 | 首次编译速度 | 推荐场景 |
|---|---|---|---|---|
| pdfLaTeX | CJK 宏包 | 需特定编码字体包 | 快 | 纯英文,或老模板兼容 |
| XeLaTeX | xeCJK 原生 | 直接用字体名 | 中等 | 中文文档首选 |
| LuaLaTeX | luatexja | 直接用字体名 | 较慢 | 需要脚本化排版 |
2.2 文档类与宏包:ctexart 和 article + ctex 怎么挑
中文文档这条路有两个入口。一个是直接用ctexart、ctexrep、ctexbook这类文档类,它们是 ctex 宏包针对中文场景预配置好的版本;另一个是照常写\documentclass{article},然后\usepackage{ctex}。
我自己的习惯是:短文档、单文件、需求简单,直接用ctexart;长文档、需要拆成多个.tex文件、后期可能换模板,就在article或book基础上单独加载ctex。原因是ctexart已经内置了一堆中文相关的默认设置(字号、行距、章节标题格式、首行缩进),你改起来要先覆盖再重设,反而绕;而用article + ctex时,宏包只负责中文字体和基础排版,其余结构你自己掌控,灵活度高。
需要说清楚的是:ctexart本质上是article加载ctex之后再补了一层中文默认样式,两者并不是对立关系。选择哪个,取决于你想不想接受那层默认样式。论文投稿如果期刊指定了模板,基本上只能走article + ctex这条路,因为模板的类文件已经定死了。
2.3 字体:Fandol 够用吗,什么时候必须换
Overleaf 预装的开源中文字体集主要是 Fandol 系列,包含宋、黑、楷、仿宋四种基本字重。日常写报告、写说明文档,这套字体完全够用,而且因为是免费开源,不存在版权问题——这一点对要公开分发的文档很重要。
设置方式很直接:
\documentclass[fontset=fandol]{ctexart}或者手动指定:
\usepackage{ctex} \setCJKmainfont{FandolSong-Regular} \setCJKsansfont{FandolHei-Regular} \setCJKmonofont{FandolFang-Regular}什么时候需要换字体?三种情况。一是模板要求特定字体(比如某些学校的论文规范明确要求宋体或黑体);二是文档里出现了 Fandol 不含的生僻字或特殊符号,编译时会报Missing character,输出成空白或方框;三是你想让标题更有设计感,需要更丰富的字重。
换字体的办法是把自己有授权的字体文件上传到项目目录,然后在配置里用Path参数指向它:
\setCJKmainfont{MyFont-Regular.otf}[ Path = ./fonts/, BoldFont = MyFont-Bold.otf, ItalicFont = MyFont-Italic.otf ]提示:上传字体文件之前先确认授权允许嵌入和分发。用在内部文档里问题不大,如果是要公开发布的材料,用 Fandol 这类开源字体最稳妥。
3. 一份能直接抄的中文文档骨架
3.1 最小可用示例逐行拆解
下面这份例子是我每次开新项目都会先贴进去跑一遍的,确认环境没问题再往上加内容:
\documentclass[12pt, a4paper, fontset=fandol]{ctexart} \usepackage{geometry} \geometry{left=2.5cm, right=2.5cm, top=2.5cm, bottom=2.5cm} \usepackage{graphicx} \usepackage{booktabs} \usepackage{amsmath, amssymb} \usepackage{hyperref} \hypersetup{ colorlinks = true, linkcolor = blue, citecolor = blue, urlcolor = blue } \title{中文文档排版实操记录} \author{某某} \date{\today} \begin{document} \maketitle \begin{abstract} 这是一段中文摘要,用来验证字体和段落缩进是否正常。 \end{abstract} \section{背景说明} 正文从这里开始。 \end{document}逐行说一下关键点。第一行fontset=fandol指定字体集,这是 Overleaf 上最省心的选项,省得你去猜字体是不是装了。geometry用来统一页边距,中文文档用 2.5 厘米左右比较舒服,太窄会显得挤,太宽阅读时视线移动距离大。hyperref让目录和引用变成可点击的链接,长文档里非常实用,但要注意它一般放在最后加载,否则容易和其他宏包冲突。
\maketitle会把标题、作者、日期按 ctex 的中文格式排出来,不需要你手动调字号。摘要环境里的文字也会自动首行缩进,这一点比某些英文模板贴心。
3.2 中文排版参数:字号、行距、缩进
中文排版和英文最大的差异在于,中文习惯更密的行距和更大的首行缩进。ctex 默认给了合理值,但如果你接了别人的模板或者想微调,需要知道这几个参数怎么设。
行距用\linespread{}调整。1.3 到 1.5 之间是比较舒服的区间,论文常见值在 1.5 左右:
\linespread{1.5}首行缩进用\parindent设置。中文规范是缩进两个汉字宽度,ctex 已经默认如此,但如果用article + ctex且遇到不缩进的情况,可以手动指定:
\setlength{\parindent}{2em}字号方面,ctex 提供了一套中文字号命令,比英文的\large系列更贴近国内习惯。常用的对照关系是:\zihao{5}是五号,\zihao{-4}是小四,\zihao{4}是四号,\zihao{3}是三号。正文通常用小四或五号,章标题用三号或四号,节标题用小四加粗。这个对照表建议在文档开头用注释记下来,改模板时能省不少搜索时间。
如果想全局改章节标题格式,用\ctexset:
\ctexset{ section = { format = \zihao{4}\bfseries, aftername = \quad }, subsection = { format = \zihao{-4}\bfseries } }aftername控制章节编号和标题文字之间的间隔,默认偏窄,中文里加一个\quad的四分之一全角空格看起来更舒服。
3.3 目录、页眉页脚与封面
目录直接用\tableofcontents生成,编译两遍之后页码就会正确。有个常见的坑:目录里的章节名如果太长会溢出,这时候可以在\section里用可选参数指定短标题:
\section[短标题用于目录]{这里是可以很长的完整章节标题}页眉页脚交给fancyhdr,配合 ctex 用没问题:
\usepackage{fancyhdr} \pagestyle{fancy} \fancyhf{} \fancyhead[L]{\zihao{-5} 文档名称} \fancyhead[R]{\zihao{-5} \leftmark} \fancyfoot[C]{\zihao{-5} 第 \thepage 页} \renewcommand{\headrulewidth}{0.4pt}注意页眉里的字号要单独设小一号,否则会比正文还抢眼。中文文档习惯在页脚写"第 X 页",比单纯一个数字更符合阅读习惯。
封面如果是内部文档,用titlepage环境手搭一个就够;如果是正式材料,一般会拿到现成的模板文件,直接改里面的字段就行,不要从零画。封面里最容易出问题的是日期格式:\today默认输出英文月份的写法,要改成中文日期得用\CTEXoptions或者手动写死,这个后面在报错那节会再提。
4. 图片、表格、公式:中文文档里的高频操作
4.1 插图的路径管理与格式选择
图片只要用graphicx就行,关键是路径管理。项目大了之后图片往往放在单独目录里,用\graphicspath统一声明,后面写文件名就不用带路径:
\graphicspath{{./figures/}{./images/}}插图的基本结构是浮动体包住:
\begin{figure}[htbp] \centering \includegraphics[width=0.8\textwidth]{example.png} \caption{示例图片的中文说明} \label{fig:example} \end{figure}[htbp]是浮动位置偏好,意思是"这里、顶部、底部、单独一页"依次尝试。中文文档里图片特别容易被挤到章节末尾,如果必须固定位置,可以加float宏包的[H]参数强制锁定,但代价是可能留下大片空白,长文档里慎用。
格式选择上,截图和照片用 png 或 jpg,矢量图用 pdf。特别注意文件名不要用中文、不要带空格,虽然现在的引擎大多能处理,但跨平台协作时是最常见的"我这儿能编你那儿报错"的来源。图片分辨率建议 300 dpi 以上,width用\textwidth的倍数来写而不是写死厘米数,这样换页面尺寸时不会跑版。
4.2 三线表和跨页长表
中文文档里的表格,学术场景讲究三线表,用booktabs是标准做法:
\begin{table}[htbp] \centering \caption{参数对照} \label{tab:params} \begin{tabular}{lcc} \toprule 参数 & 默认值 & 建议值 \\ \midrule 行距 & 1.0 & 1.5 \\ 首行缩进 & 0pt & 2em \\ 正文字号 & 10pt & 小四 \\ \bottomrule \end{tabular} \end{table}\toprule、\midrule、\bottomrule三条线的粗细不同,这种视觉层次是 booktabs 的核心价值,别用\hline去替代,出来的效果差距很明显。
表格跨页是个老问题,tabular环境不能自动断页。内容长就用longtable,它支持跨页并自动重复表头:
\begin{longtable}{lcc} \caption{长表格示例} \\ \toprule 项目 & 数值 & 说明 \\ \midrule \endfirsthead \toprule 项目 & 数值 & 说明 \\ \midrule \endhead \bottomrule \endfoot A & 1 & 第一行 \\ \end{longtable}\endfirsthead和\endhead这两段是分别给首页和后续页定义表头的,写起来啰嗦但一次搞定。
列宽需要自适应的话用tabularx,它能按\textwidth自动分配列宽,中文长文本放进表格时特别有用,否则内容会直接撑破页面。
4.3 公式与中文混排的间距问题
公式用amsmath提供的环境,行内公式用$...$,独立公式用equation,多行对齐用align:
\begin{align} S &= \sum_{i=1}^{n} w_i x_i \\ \bar{x} &= \frac{1}{n}\sum_{i=1}^{n} x_i \end{align}中文文档里公式最常见的两个毛病:一是公式前后的间距看着别扭,二是公式里的中文用错方式。第一点可以在导言区加\setlength{\abovedisplayskip}{6pt}之类的微调,但一般不建议乱改,默认值经过长期打磨,改不好整篇的节奏都乱。第二点要记住,公式里要写中文必须用\text{}包起来:
\begin{equation} \text{准确率} = \frac{\text{正确样本数}}{\text{总样本数}} \end{equation}直接在里面写中文,输出会变成没有断行处理的散乱字符,字形也可能不对。
注意:数学模式里
_、^、%、&、#、$都是特殊符号,正文里要显示它们必须转义成\_、\^、\%、\&、\#、\$。中文文档里写文件路径、写代码变量时最容易在这个上面翻车。
5. 参考文献与引用:国标样式怎么落地
5.1 bib 文件怎么组织
参考文献全部放进.bib文件,每条记录用关键词标记:
@article{zhang2023example, author = {张三 and 李四}, title = {一个中文文献条目的示例}, journal = {某某学报}, year = {2023}, volume = {45}, number = {3}, pages = {112--120}, language = {zh} }几个细节值得强调。中文作者之间用and连接,不要用顿号,否则解析会出错。中文文献建议加language = {zh},国标样式会根据这个字段调整标点,比如中文文献用中括号还是圆括号、作者后面加"等"还是"et al.",都跟它有关。页码用两个连字符--,不要写一个短横,否则渲染出来长度不对。
.bib文件建议按主题拆成多个,比如refs-theory.bib、refs-data.bib,主文件里分别\addbibresource或者\bibliography{refs-theory,refs-data}。这样引用多的时候查找方便,也不容易因为一个文件损坏影响全部。
5.2 gbt7714 和 biblatex 两条路线
国内文档要符合国标格式,主流有两条路线。一条是gbt7714宏包配 BibTeX:
\usepackage[sort&compress]{gbt7714} \bibliographystyle{gbt7714-numerical} \bibliography{refs}gbt7714-numerical是顺序编码制,正文引用显示为数字上标;要改成著者—出版年制,换成gbt7714-author-year即可。sort&compress选项会自动把连续引用压缩成"1-3"这种形式。
另一条是biblatex配合biblatex-gb7714-2015:
\usepackage[backend=biber, style=gb7714-2015]{biblatex} \addbibresource{refs.bib}这条路线更现代,对多语言混排、标注细节的控制能力更强,代价是要用biber而不是bibtex作为后端,编译流程不同,第一次配容易搞混。
我的建议是:如果只是普通报告、论文,gbt7714够用且上手快;如果文档里中英文献混杂很多、需要精细控制,再上biblatex。不要在项目中途换路线,切换成本比想象中高。
5.3 编译顺序:为什么引用老是变成问号
这是新手最高频的困惑。正文里的\cite{}编译出来是一堆问号,不是配置错了,而是编译次数不够。
传统 BibTeX 的完整流程是四步:XeLaTeX 编译一次生成.aux文件,BibTeX 读.aux和.bib生成.bbl,然后再 XeLaTeX 编译两次把引用编号和参考文献表写进正文。少任何一步,问号就会出现。
Overleaf 上一般不需要手动控制,它内部会自动跑足够多次。但如果引用还是问号,可以先看日志里有没有Citation undefined的警告,通常原因是:bib 文件里没有这个 key、key 拼写不一致(大小写敏感)、或者\bibliography{}里的文件名和实际文件名不符。还有一个容易忽略的点:如果 bib 文件是在编译过程中才上传的,需要重新触发一次完整编译。
| 现象 | 常见原因 | 处理方式 |
|---|---|---|
| 引用显示为问号 | 编译次数不足 | 重新编译,确认跑了 bib 流程 |
| 警告 Citation undefined | key 拼错或不存在 | 核对 bib 文件里的 key |
| 参考文献表空白 | bib 文件名不匹配 | 检查\bibliography{}参数 |
| 中文文献标点异常 | 缺 language 字段 | 补上language = {zh} |
6. 协作、修订模式与版本管理
6.1 多人同时编辑的实际情况
Overleaf 的多人在线编辑和文档类工具体验类似,几个人可以同时改同一个文件,光标位置会标出不同颜色。实际用下来有几个经验值得分享。
如果多人同时改同一段,冲突会发生,只是它处理得比手动合并友好——通常表现为某一方的改动被覆盖,需要重新输入。所以团队协作时最好提前分工到章节,各改各的,减少同段落并发。另外,中文输入法在浏览器里的候选框偶尔会遮挡光标位置,写长段落时建议用本地编辑器写好再粘贴进去,或者用 Overleaf 的"离线编辑同步"思路:本地用编辑器改.tex,再上传覆盖。
还有一点:中文文档里经常有人用批注(Comment)标问题,批注和正文要分清楚。批注适合"这里数据待确认"这种短期问题,不适合当正式说明,定稿前记得清空。
6.2 修订模式(Track Changes)的正确用法
修订模式是我最推荐的功能之一,特别适合导师改论文、上级审报告这类场景。开启之后,所有增删改都会以标记形式保留,谁改的、改了什么、什么时候改的都能追溯,审阅人可以逐条接受或拒绝。
使用上有几个实操建议。第一,开启修订模式之后再动手改,别改完了才想起来开,那样不会留下记录。第二,修订记录积累多了会很乱,建议按轮次处理:一轮审阅结束后集中接受或拒绝,清空记录,再开下一轮。第三,修订模式只保留内容层面的改动,格式调整一般不会标注,如果同时对排版做了调整,最好在正文里留一句说明。
提示:修订模式和批注功能的具体可用范围跟当前订阅方案有关,动手前先在编辑器里确认一下入口位置和权限,免得改到一半发现开不了。
6.3 用 Git 做版本管理兜底
在线编辑器再方便,也不如版本管理踏实。Overleaf 提供了 Git 通道,可以把项目同步到本地仓库,用熟悉的 Git 命令做分支、回滚、比对。就算不用它的集成入口,也可以本地建一个 Git 仓库管理.tex源码,定期把项目打包下载覆盖过去。
对中文文档来说,版本管理的价值主要体现在三处:一是大改之前能留个存档,改砸了随时回去;二是多人协作时能看清谁在哪次提交里动了哪一节;三是可以给不同版本打标签,比如"送审版""终稿版",避免文件名里堆满"最终最终版2"。
实际操作上我习惯每完成一个章节就提交一次,提交信息写清楚改了什么,比如"补充第三章表格说明"。这样做的好处是几个月后回头查某个数据的来源,翻日志比翻文件快得多。
7. 报错排查速查与踩坑记录
7.1 编译类报错
Emergency stop和TeX capacity exceeded是我遇到最多的一类,本质都是语法结构没闭合。最常见的是漏了\end{document}、环境嵌套写错(比如在figure里开了table没关)、或者花括号数量对不上。排查办法是看日志里报错位置的行号,往前后各看二十行,绝大多数能找到缺的那个符号。
Runaway argument通常指向花括号不配对,或者某行里有个%把后面的闭合符号注释掉了。这种情况我一般会临时把报错附近几行的%全部去掉,重新编译看是否通过,定位到具体行再恢复。
Too deeply nested是列表嵌套层数超出限制,中文文档里写多级清单很容易触发。解决办法是把四层以上的嵌套改成用段落或者表格表达,层次太深本身阅读体验也不好。
7.2 字体和中文相关的报错
Font "XXX" not found意思是引擎找不到你指定的字体。在 Overleaf 上,先确认字体名拼写和官方给的名称一致,比如 Fandol 系列的名字是FandolSong-Regular这种带后缀的完整形式,少写-Regular就会找不到。如果是自己上传的字体,检查Path参数指向的目录是不是相对项目根目录,以及文件后缀是.otf还是.ttf。
Missing character是字体里没有这个字形,输出会是空白或者方框。生僻字、某些特殊符号最容易触发。处理办法是换一个覆盖范围更全的字体,或者用\fontspec临时切换到其他字体来显示这一个字符。
CTeX fontset 'xxx' is unavailable说明fontset参数填的字体集在当前环境里不存在。Overleaf 上保险的选项是fandol,不要照搬别人本地的windows或mac配置,那些参数在你的环境里根本不成立。
7.3 图片、路径、引用方面的报错
File 'xxx.png' not found九成是路径或大小写问题。Linux 环境下的编译对文件名大小写敏感,Fig1.PNG和fig1.png是两个文件。中文文件名虽然多数情况能处理,但建议一律改成英文小写加下划线。
Undefined control sequence是用了没加载的宏包里的命令。看到这个报错先想:这个命令来自哪个包?比如\toprule来自booktabs,\includegraphics来自graphicx,\text{}来自amsmath。大部分情况下导言区补一行\usepackage{}就好了。
There were undefined references是交叉引用没解析,跟引用问号同理,再编译一次基本能解决。如果反复出现,检查\label和\ref的名字是否完全一致,包括大小写和冒号后面的部分。
7.4 常见问题速查表
| 报错关键词 | 大概率原因 | 首选动作 |
|---|---|---|
| Emergency stop | 环境或花括号未闭合 | 查报错行前后二十行 |
| Runaway argument | 花括号不配对或%误注释 | 临时注释掉可疑行试验 |
| Font not found | 字体名拼写或路径错误 | 核对完整字体名与 Path |
| Missing character | 字体缺字 | 换字体或局部切换字体 |
| File not found | 路径、大小写、文件名 | 改英文小写文件名 |
| Undefined control sequence | 缺宏包 | 补对应\usepackage |
| Citation undefined | 引用 key 不匹配 | 核对 bib 文件中的 key |
| Missing $ inserted | 特殊字符未转义 | 检查_ ^ % & # $ |
8. 一些提升效率的个人习惯
8.1 文件组织
项目文件我一般拆成四部分:主文件只管导言区和\input各个章节,正文按章拆成chap1.tex、chap2.tex,图片统一放figures/,参考文献放refs.bib。这么做的好处是单文件不会膨胀到几千行,找内容靠文件名就能定位,多人协作时也更容易分工。
主文件里用\input{}而不是\include{},因为\include会强制分页并生成额外的 aux 文件,写普通文档没必要。真正需要单独编译某一章的场合很少,用不上那个机制。
8.2 编译速度
文档超过三四十页之后,全量编译会明显变慢。有几个办法能缓解。一是把不常改的大段内容(比如附录)暂时\input注释掉,定稿前再打开。二是图片尽量压到合适的分辨率,一张几兆的原图放进文档,编译时间会肉眼可见地涨。三是草稿阶段先不挂参考文献,引用先用占位文字,最后再统一接上 bib 流程。
还有一个容易被忽略的点:hyperref宏包在文档很大时对编译时间有一定影响,草稿阶段可以先注释掉相关的\hypersetup配置,定稿前再恢复。
8.3 几个小细节
日期格式。\today默认输出英文月份,要中文日期最省事的办法是直接写死:
\date{2024 年 6 月}标题里的标点。中文标题里如果用冒号或问号,注意全角和半角的选择,混用会让整篇看起来不一致。我一般正文用全角、代码和文件名用半角,全文保持这一条规矩就行。
目录深度。默认ctexart只显示到 subsection,如果你的文档结构比较深,可以用\setcounter{tocdepth}{3}放开到 subsubsection,但层级太深目录会很长,反而不好查。
空行。LaTeX 里空行代表分段,中文文档里如果只是想换行不换段,用\\或者\newline,千万别靠敲空行实现,那样会多出缩进和段间距,排版看着就乱了。
最后说一个我踩得最深的坑:不要一边写一边纠结排版。中文文档的历史版本里,我前期花在调行距、改字体、试页边距上的时间,比写内容本身还多。正确的顺序是先用最朴素的默认配置把内容写完,确认逻辑没问题,最后统一做视觉调整。内容定稿之后调格式,改一处动全局,效率比边写边调高好几倍。这个顺序反过来做,你会不停地在"改完格式发现内容还要重写"之间来回折腾,那才是真的费时间。