ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

LaTeX双栏模板跨栏图表排版详解:dblfloatfix实战指南

LaTeX双栏模板跨栏图表排版详解:dblfloatfix实战指南 写毕业论文的那段日子我几乎被LaTeX双栏模板里的跨栏图表折磨疯了。明明单栏插图都好好的一到figure*这种跨栏环境图表就开始“不听话”——有的跑到文章最后一页有的直接消失有的风格怪异地在页面顶部孤零零地待着。后来接触到dblfloatfix这个宏包才算是把跨栏浮动结构这摊子事彻底理顺。如果你也在用IEEEtran、ACM或者各种学报的双栏模板写论文这篇就是我踩完坑之后整理出来的实战笔记。这个内容不是什么高深的理论课它解决的就是一个非常具体的排版问题如何在双栏文档中让宽表格或大图稳定地出现在你想要的位置。适合正在写双栏论文、需要插入跨栏图表、又不想被LaTeX的浮动体机制反复折磨的同学。我会从双栏浮动结构的基本逻辑讲起再把dblfloatfix的原理、用法、参数、坑点逐个拆开最后附上我实测过的问题排查清单。1. 跨栏图表为什么这么难搞1.1 先搞清楚figure*和table*到底是什么在双栏文档里插入单栏图片用的是figure环境它只会占据当前这一栏的宽度跟在Word里插个小图差不多。而跨栏图表也就是横跨整个页面宽度的图表LaTeX里必须用带星号的浮动环境也就是figure*和table*。很多人第一次用figure*的时候会理解错以为它只是“把图片放大一点”其实它改变的是浮动体的“物理属性”。单栏浮动体只能在当前栏内移动跨栏浮动体则是在整个页面级别上移动。这个区别直接导致了后续所有排版行为的不同。用IEEEtran模板举例双栏页面正文宽度大约是7英寸左右单栏宽度只有3.5英寸。如果你在单栏环境里塞一张宽度为6英寸的图LaTeX会直接报Overfull \hbox警告图片超出栏宽跟旁边的文字叠在一起。而figure*环境可以让这张图占用整个7英寸的宽度并且让正文文字自动绕到下方形成整齐的分栏边界。关键点在于figure*并不会自动把你放到想要的位置。它只是给了你一个“可以在整个页面里浮动”的资格具体放在哪里由LaTeX底层的浮动算法说了算。1.2 双栏文档里浮动体的放置逻辑LaTeX处理浮动体的核心逻辑是先把位置排出优先级再根据页面剩余空间决定是否放置。对于普通单栏浮动体位置参数有htbp四种优先级h表示当前位置t表示页顶b表示页底p表示单独一页。跨栏浮动体的情况就有点复杂了。在标准LaTeX中figure*的位置参数虽然也可以写htbp但实际处理时会受到更多限制。尤其是一些老版本模板里跨栏浮动体放到页底的支持是很弱的甚至直接不支持b选项。这其实跟双栏文档的页面构建方式有关。双栏模式下LaTeX会把每一页分成左右两个半页来处理正文分栏排版之后再处理浮动体。单栏浮动体是在栏级别操作的而跨栏浮动体必须在整个页面排版完成之后才能插入。这个“后处理”步骤大大限制了它的可选位置所以很多跨栏图表最后都被挤到了文末或者干脆到了最后一页。1.3 默认跨栏浮动体有哪些坑我平时用得比较多的是IEEEtran和ACM模板这两类模板对跨栏图表的默认处理都不算友好。踩过的坑大致有这几类第一种是图表跑到文章最末尾。你明明在第三节引用了这张图但它就是翻到参考文献后面才出现。这种情况最常出现在图表很多的长论文里因为浮动体队列积压页面顶部的跨栏槽位一直被占着后面的跨栏浮动体只能一路排到文末。第二种是位置参数失效。你写了\begin{figure*}[htbp]但LaTeX完全无视图表就是不按你的要求来。这其实是LaTeX浮动算法的正常表现位置参数只是“建议”不是“命令”。当页面空间不足时LaTeX宁可把浮动体延后也不会强行压缩正文来塞图。第三种是双栏页顶的跨栏图表和单栏浮动体争夺空间。有些模板里跨栏图表的页顶区域会和单栏浮动体的页顶区域重叠导致图文错位、编号混乱。这个问题在默认模板下尤其明显需要一个专门的宏包来协调。2. dblfloatfix这个宏包到底干了什么2.1 宏包的设计思路dblfloatfix是Thomas Fehd写的一个小宏包代码量不大名气和graphicx、amsmath没法比但在处理双栏浮动体问题上非常干净利落。它的核心目标只有一个修复跨栏浮动体不能放到页底的问题并改善位置参数的响应能力。LaTeX内核里面对跨栏浮动体的处理一直有一个短板就是页底放置支持不完整。这个问题从LaTeX2e时代就存在官方在fixltx2e里曾经提供过一部分修复但效果有限。dblfloatfix在底层重新定义了一些内部命令把b选项对跨栏浮动体的支持补上了。使用方式相当简单在导言区加一行\usepackage{dblfloatfix}加载之后figure*和table*的放置逻辑就会有一些改变。最直观的变化是[b]参数不再被无视跨栏图表可以被放到页面底部了。2.2 为什么不是p选项也没问题熟悉浮动体的人可能会问既然跨栏图表这么难放为什么不直接加p参数让它单独成页如果图表特别大这确实是个办法。但绝大多数论文里的图没有大到需要独占一页只因为排版机制的问题就把页面空出来浪费版面不说审稿人看着也难受。dblfloatfix的意义在于它让跨栏图表能更好地利用现有页面的剩余空间。比如页面底部还有大约三分之一栏高的空白单栏浮动体放不下正文凑不齐这时候跨栏图表放到页底就是一个非常优雅的选择。有了这个宏包这类空间就能被有效利用起来。而且dblfloatfix不只是增加了b支持它还调整了一些内部计数器优化了跨栏浮动体在页面顶部的排列策略。实测下来用了它之后跨栏图表跑到文末的情况会明显减少。2.3 跟其他方案的取舍双栏排版的问题解决方案不止一个dblfloatfix其实是比较“正统”的一种。我在网上还见过midfloat、floatcol、dblfloatfix的兄弟包stfloats以及人工干预的\afterpage方案。stfloats是另一个老牌宏包主要也是解决浮动体放页底的问题。但它的侧重点是单栏浮动体的页底放置对跨栏环境的优化不如dblfloatfix那么直接。我的建议是如果只是普通双栏模板里插跨栏图dblfloatfix是首选。midfloat则适合那种需要把图表固定在某一栏中间与正文特定位置对齐的场景它提供了一种和各栏文本进行定位的方式代价是手动干预多比较麻烦。\afterpage方案我也试过思路是在某页结束之后强制插入浮动体能够在某些特殊情况里发挥作用但它要求你必须知道图表所在的准确页码而且插入位置和浮动体的交互逻辑经常出bug调试成本太高。综合比较下来dblfloatfix是在“改动最小”和“效果最稳”之间权衡得最好的方案。3. 实战操作一步步把跨栏图表放对位置3.1 环境准备与宏包引入开始之前建议先确认你的LaTeX发行版是完整的TeX Live或者MiKTeX。这两个发行版本身都自带了dblfloatfix宏包不需要额外去CTAN下载直接在导言区引用就行。我的一个最小可用模板长这样\documentclass[journal]{IEEEtran} \usepackage{graphicx} \usepackage{booktabs} \usepackage{dblfloatfix} \usepackage{lipsum} % 生成测试文本 \begin{document} \lipsum[1-3] \begin{figure*}[t] \centering \includegraphics[width\textwidth]{example-image} \caption{这是一个跨栏图片示例} \label{fig:wide} \end{figure*} \lipsum[4-6] \end{document}注意这里的width\textwidth在figure*环境中\textwidth代表的是整个页面的文本宽度而不是单栏宽度。所以图片可以放心铺满整行。如果你在单栏figure里也用\textwidth那图片宽度就只有栏宽那么大这正好能直观感受到两种浮动环境的区别。3.2 位置参数选择与模板兼容性dblfloatfix加载之后位置参数的使用就有一些讲究了。根据我实测的经验跨栏图表最稳妥的参数是[t]或者[b]也就是页顶或页底。[h]参数对跨栏浮动体来说依然不太可靠因为这个宏包并没有把“当前位置”的跨栏支持做到完美。多个跨栏图表需要不同位置时建议使用[!t]、[!b]这样的加强版参数感叹号会告诉LaTeX把位置参数带来的限制放宽尽量按照你的要求来。但要提醒一句感叹号只是提高优先级不是强制如果页面空间实在不够LaTeX仍然会把图表推迟。我经常用的一组合适配置% 宽表格放页顶 \begin{table*}[!t] \centering \caption{实验数据对比} \label{tab:compare} \begin{tabular}{lcccc} \toprule 方法 数据集A 数据集B 数据集C 数据集D \\ \midrule Baseline 0.72 0.65 0.81 0.77 \\ Ours 0.85 0.79 0.88 0.91 \\ \bottomrule \end{tabular} \end{table*} % 大图放页底 \begin{figure*}[!b] \centering \includegraphics[width\textwidth]{architecture} \caption{整体架构图} \label{fig:arch} \end{figure*}需要注意的是dblfloatfix对IEEEtran模板的适配比较成熟但如果你用的是自己学校的学位论文模板就要特别测试一下。有些模板自己修改了\dbltoproom这些内部参数会跟宏包的逻辑冲突表现为编译报错或者跨栏图表仍然跑到文末。3.3 处理多个跨栏图表写长论文时跨栏图表往往不止一个。我有一篇论文就遇到了三个跨栏图、两个跨栏表的情况全部堆在同一篇文章里如果没有合理的编排策略浮动体会互相挤压版面很容易乱掉。我的经验是不要给每个跨栏浮动体都指定复杂的位置参数尽量只使用[t]和[b]并且让它们在全文中有规律地交替。比如第一节放页顶图第二节放页底表第三节再放页顶图。这样页面空间的利用会更均衡不会出现前两页顶部堆了一堆图、后面几页完全没图的情况。还有一个额外经验跨栏图表尽量在正文里用\ref显式引用几次比如“如图~\ref{fig:arch}所示”。LaTeX内部有一个机制被正文引用的浮动体在放置时会获得更高的优先级虽然这个机制在跨栏环境的实际效果不如单栏那么明显但多引用总没坏处。如果两个跨栏图表恰好出现在相邻页而且都是[t]LaTeX会出现错位也就是第二个图跑到第一个图前面因为浮动体的延迟放置机制。我用一个很简单的办法解决在第二个图表的位置前面用\clearpage强制分页把两个浮动体的放置空间彻底隔开。3.4 和caption、subcaption配合实现复杂排版论文里经常出现一个大图里包含多个子图的排版需求这时候要配合subcaption宏包使用。跨栏大图加子图是双栏文章中常见的“图版”结构。\usepackage{subcaption} \begin{figure*}[t] \centering \begin{subfigure}{0.45\textwidth} \includegraphics[width\textwidth]{sub1} \caption{第一个子图} \label{fig:sub1} \end{subfigure} \hfill \begin{subfigure}{0.45\textwidth} \includegraphics[width\textwidth]{sub2} \caption{第二个子图} \label{fig:sub2} \end{subfigure} \caption{包含两个子图的跨栏图版} \label{fig:combined} \end{figure*}注意这里的0.45\textwidth因为跨栏环境的\textwidth是整页宽度两个子图之间再用\hfill拉开距离正好可以并排摆下。如果是在单栏环境里同样的代码就会显得特别挤因为两者的基准宽度完全不同。subcaption和dblfloatfix的兼容性整体来说不错但有版本差异。我遇到过旧版的subcaption包与dblfloatfix在页底跨栏图表共用时会报错的情况当时的解决办法是把subcaption升级到最新版本或者改用subfig包。现在主流发行版的宏包都更新过了这个问题基本不太会遇到但还是建议你在写论文前把宏包都更新到最新版。4. 跨栏图表排版的进阶玩法4.1 底栏跨栏的特殊处理dblfloatfix带来的最核心变化就是跨栏图表可以放到底部了。但这个能力是有代价的页面底部的跨栏浮动体会把原本左右两栏底部的文字都顶下去如果一个页面同时有脚注、页底浮动体排版会变得很拥挤。实际操作中如果页面底部放了跨栏图表下面通常不能再放脚注否则表格和脚注会重叠。有些模板会主动调整这个布局但如果你发现页底跨栏表压住了脚注最简单粗暴的办法是给对应页面加\enlargethispage{\baselineskip}之类的命令把页面撑大一点点给脚注腾出空间。另一种处理方式是故意让底栏跨栏图表“插入”在正文段落的最后一行之间形成一种被文字环绕的视觉效果。这个需要用\vspace微调不推荐新手一开始就尝试因为排版很容易崩。4.2 表格和图片混排注意事项跨栏表格和跨栏图片混排时最麻烦的问题是表格通常需要更宽的排版空间但又不希望表格占据整个页面的视觉重心。宽表格建议加上booktabs宏包提供的\toprule、\midrule、\bottomrule三线表样式这样就算跨到整页宽度也不会显得呆板。图片方面graphicx宏包的width\textwidth是最常用的但要注意如果图片是矢量图比如PDF或EPS格式缩放时线条粗细也会跟着变缩放比例太大会让线条显得过细。这种情况建议在绘图时就按最终排版尺寸来设计而不是靠LaTeX硬缩。还有一个小细节是图片路径。如果图放在子目录里记得设置\graphicspath{{figures/}}并且确保文件名不要带空格。跨栏图表因为比较容易触发浮动体排队如果一个图片文件缺失编译报错之后整个浮动体队列都会卡住现象就是后面所有的图和表都不显示了排查起来非常费劲。4.3 行距、页边距对跨栏图表的影响跨栏图表能不能顺利放到目标位置跟页面空间的设定有很大关系。页边距越大、正文行距越宽页面剩余空间就越容易被撑满跨栏图表的放置窗口就越小。IEEEtran这些标准模板的页面参数已经做过优化不需要再调整。但如果你用的是自定义的学位论文模板页边距动不动就3厘米以上这时dblfloatfix的效果会被削弱。我自己的处理办法是用geometry宏包重新定义页边距或者把跨栏图表尽量安排在新的小节开始的位置因为小节开头通常会有一段空白浮动体可以利用这段空白完成排版。\floatsep、\textfloatsep这两个长度参数也值得了解。\floatsep控制同一页多个连续浮动体之间的距离\textfloatsep控制浮动体与正文之间的距离。对于跨栏图表适当增大\textfloatsep可以让图与文字之间的呼吸感更强避免图贴着字显得拥挤。\setlength{\textfloatsep}{8pt plus 2pt minus 4pt} \setlength{\floatsep}{4pt plus 2pt minus 2pt}实测下来把\textfloatsep设置为8到12磅是视觉效果最好的范围。注意后面那个plus和minus是弹性值让LaTeX在排版时可以根据页面空间微调距离建议保留。5. 常见问题与排查技巧实录5.1 图表一直跑到文末怎么办这是被问得最多的一个问题。图表跑到文末本质原因就是浮动体队列的积压。跨栏图表太多、页面空间不足、位置参数配置不当任何一个环节出问题都会导致这个结果。排查时先看编译日志搜索LaTeX Warning: Float too large for page by X pt。日志里会明确告诉你某个浮动体超出页面多少磅这是一个非常直接的线索。如果日志显示float too large那就是图表本身太大就算把整个页面空出来也放不下这种要先缩小图片或者调整表格字号。如果是多个浮动体积压我建议先删掉一部分位置参数统一改成[!t]然后逐步编译看效果。再不行就在每个跨栏图表前加\clearpage强制分页虽然会让页面变稀疏但总能保证图的位置按顺序来。5.2 跨栏图表和单栏浮动体位置冲突双栏页面里跨栏图表占了页面顶部之后单栏浮动体就只能往下找位置。这种冲突是正常的但如果图表的编号顺序出现错乱比如第二个图表显示在第一个图表之前那问题就严重了。这种情况八成是浮动体在队列里的次序乱了。LaTeX处理浮动体是严格按照源代码顺序入队的但入队之后实际排版位置会受到空间影响。两个相邻的跨栏图表都放在[t]时第一个图表如果因为尺寸稍大而暂时无法放置第二个图表就可能先被放置造成顺序颠倒。我的经验是给需要严格保持顺序的跨栏图表添加\FloatBarrier这个命令来自placeins宏包会强制把之前的浮动体先排完再继续后面的内容。虽然它不能彻底解决所有顺序问题但用来控制关键位置非常有效。5.3 编译报错Not in outer par mode这个报错出现得很突然而且一旦出现就很容易让人懵。它的意思是你用了浮动体环境但它出现在了另一个浮动体环境内部。常见的原因是把figure*写进了table或者figure环境里比如\begin{table} \begin{figure*} ... \end{figure*} \end{table}这属于环境嵌套错误LaTeX完全不允许这种写法。解决办法很简单把跨栏图表的figure*环境从单栏环境的内部挪出来放到段落层次。还有另一种可能是某个模板里面的宏包内部处理不当在浮动体中调用了\captionof之类的命令。这种情况少见但也要留意。排查时可以直接搜索文档里所有figure*和table*的位置检查它们是否都出现在正文级别。5.4 问题排查速查表我把平时遇到的典型情况整理成了一张表方便你出问题时快速对照现象可能原因解决办法跨栏图表跑到文末浮动体队列积压减少跨栏图表数量使用[!t]必要时加\clearpage图表顺序错乱浮动体延迟放置用\FloatBarrier或给相邻图表强制分页页底跨栏表压住脚注页面空间不足调小该页段落间距或改用[t]放置编译报Not in outer par mode浮动环境嵌套检查figure*是否在figure内部移出即可图表超宽出界尺寸设置错误检查是否使用\textwidth缩小图片宽度加载dblfloatfix后模板异常模板内部命令冲突更新宏包或改用stfloats方案5.5 一个屡试不爽的终极技巧折腾完上面所有内容之后最后分享一个我自己多年写双栏论文总结出来的技巧跨栏图表的位置问题很多时候不是排版问题而是写作节奏问题。如果你把一个跨栏图表放在某个小节的末尾而这个小节只剩两三行文字LaTeX几乎必定会把这个图表推迟到下一栏甚至下一页。因为对它来说把图表放在这个位置太“浪费”版面了。反过来如果你把图表放在一个小节的开始紧跟在小节标题后面页面顶部刚好有空间这个图表就会老老实实待在那里。所以我在写作时会有意识地调整图表在正文中的位置而不是死等LaTeX自动排版。比如某一节开头有五六行文字的介绍再放图表这比在节末尾添一个图要稳妥得多。这个方法放之四海而皆准也是我用了dblfloatfix之后最核心的“懒人秘诀”。dblfloatfix说到底只是一个工具工具再好也要理解背后的浮动体逻辑才能用顺手。希望这篇实战笔记能帮你少踩几个我当年踩过的坑早点把版面稳住、把论文写完。如果你在具体用的时候遇到其他奇怪的问题欢迎在评论里一起讨论。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进