页面顶端的页眉和底部的页码,回答的是同一个问题:我现在读到书的哪儿了?这个装置比印刷术还古老——中世纪的抄写员会在写本上端的空白处专门划出一行,写上一个标题,好让翻页的读者分辨自己身处抄本的哪一部分。LaTeX 把这项工作交给一套叫做 页面样式 的机制:用 \pagestyle 选择四种内置样式,不够用时再换上标准宏包 fancyhdr。本页就沿着这条路走一遍:为什么每章第一页的页眉会消失,\leftmark 与 \rightmark 如何把章、节标题引到页眉里,以及 \pagenumbering 怎样让前置部分用罗马数字、正文用阿拉伯数字。
\pagestyle 可选的四种页面样式
在原生 LaTeX 里,页眉和页脚不是一处一处地设置,而是整套切换——这套东西叫 页面样式。在导言区写 \pagestyle{headings},从这里到文末的每一页都会生效;只想改动某一页时,正文中的 \thispagestyle{empty} 只覆盖当前这一页。标准提供的样式恰好是四种。
| 样式 | 显示什么 |
|---|---|
empty | 页眉与页脚皆空;连页码也没有 |
plain | 页眉为空,页脚居中只放页码。article / report 的默认样式 |
headings | 页脚为空;页眉承载章、节标题和页码。book 的默认样式 |
myheadings | 布局与 headings 相同,但自动更新停止:文字由 \markboth / \markright 自行提供 |
哪一种一开始就生效,取决于文档类。article 和 report 从 plain 起步——除了页脚居中的页码之外一无所有;book 从 headings 起步,顶端流淌着章、节标题。这种区别并非随意:十页的论文用不着每页都宣告「我在哪」,而在四百页的书里,页眉正是读者从索引跳回正文的落脚点。
headings 究竟往页眉里放什么,同样由文档类决定。在双面的 book 中,偶数(左)页放章标题,奇数(右)页放节标题,页码则始终落在外侧(切口一侧)。选择 myheadings 会关掉自动更新,改由你用 \markboth{左页}{右页}(双面)或 \markright{右页} 亲自提供文字。不过内置样式的弹性也就到此为止:连「左边文档名、右边页码」这样朴素的版式都做不到。再往前,就是 fancyhdr 的活了。
为什么每章第一页的页眉不见了
答案就写在 \chapter 的定义里。在 book.cls 中,\chapter 换页之后的第二行正是 \thispagestyle{plain}。于是章的首页不管你设了什么,都会切换成 plain——没有页眉,只在页脚居中放一个页码。\part 和 \maketitle 做的是同一件事。明明写了 \pagestyle{empty},标题页和每章开头却还留着页码,原因就在这里。
该怎么修,取决于你想要什么。若只是想连页码一并去掉,就在 \chapter{…} 的 紧后面 写 \thispagestyle{empty};写在导言区没有用,因为 \chapter 会在执行的那一刻覆盖设置。反过来,若希望章的首页与全书其余部分一致,那就重造 plain 这个样式本身。fancyhdr 的 \fancypagestyle{plain}{…} 正是为此而设:只要定义一次,之后每个 \chapter 去取 plain,拿到的都是你自己的设计,而不是文档类的。
% Fix 1: drop the page number too, on this chapter page only.
% This must come AFTER \chapter, never in the preamble.
\chapter{Introduction}
\thispagestyle{empty}
% Fix 2: redefine plain, so every chapter opening follows your design.
\fancypagestyle{plain}{%
\fancyhf{}%
\fancyfoot[C]{\thepage}%
\renewcommand{\headrulewidth}{0pt}%
}\pagestyle{fancy}:fancyhdr 打开的六个槽位
载入 fancyhdr 并声明 \pagestyle{fancy},页眉和页脚就各自打开左(L)、中(C)、右(R)三个位置,一共六个槽位,随你往里填东西。作者是 Pieter van Oostrum,宏包里的版权行从 1994 年一路写到今天。这个被削短的名字背后有段来历:最初的版本叫 fancyheadings.sty,可当年仍在服役的 MS-DOS 只保留文件名的前八个字符,落到磁盘上就成了 fancyhea.sty。于是有人开始写 \usepackage{fancyhea},这类文档到了 Unix 上就编译不过。作者被这件事烦得够呛,索性把宏包改名成刚好八个字符的 fancyhdr。
实践中的定式是先用 \fancyhf{} 清空六个槽位,再只填需要的那几个。略过这道清扫,文档类原有的页眉可能仍留在下面,同一段文字会出现两次。填写时页眉用 \fancyhead[L]{…} / [C] / [R],页脚用 \fancyfoot[L]{…} / [C] / [R];表示位置的字母可以连写,例如 \fancyhead[LO,RE]{…} 一次设定多个槽位。
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhf{} % clear all six slots first
\fancyhead[L]{Document title} % header, left
\fancyhead[R]{\thepage} % header, right: the page number
\fancyfoot[C]{\today} % footer, centre在双面(twoside)文档里,位置还要与 偶数页(E)、奇数页(O) 组合。[LE,RO] 意为「偶数页在左、奇数页在右」,也就是跨页外侧、切口那一角——页码传统上的落脚点。既不带 E 也不带 O 的写法如 [L],则在两种页面上放同样的内容。页眉下方与页脚上方的横线由 \headrulewidth 和 \footrulewidth 控制,默认分别是 0.4pt 与 0pt(无线)。注意这两个是宏而不是长度:要用 \renewcommand 修改,而不是 \setlength——几乎每个人都会在这里栽一次。
\renewcommand{\headrulewidth}{0.4pt} % header rule; this is the default
\renewcommand{\footrulewidth}{0pt} % no footer rule; also the default把章标题放进页眉:\leftmark 与 \rightmark
写下 \fancyhead[L]{\leftmark},该页的章标题就会落进页眉。在 book / report 中,\leftmark 保存当前章、\rightmark 保存当前节,每处理一次 \chapter 或 \section,其内容就被替换一次。article 没有章,于是整体下移一级:双面时 \leftmark 装节、\rightmark 装小节;默认的单面则由 \rightmark 装节。
这套机制的地基是 TeX 的 \mark 原语。TeX 每排完一页,都会把该页上出现的标记分开保存两个:第一个(\firstmark)和 最后一个(\botmark)。LaTeX 内核据此把 \leftmark 定义为 \botmark 的左半部分,把 \rightmark 定义为 \firstmark 的右半部分。左右取「最后/最初」这种不对称,只要想想辞书的书眉就明白了——页顶的指引词必须是这一页上实际排出的头一条与末一条,才谈得上有用。这个设计在实务中也会露面:当某一节从页面中间开始时,\rightmark 取的是本页第一个标记,于是页眉写的不是上半页那一节,而是 刚在下半页开始的新节。这是规格内的行为,不是 bug。
另一处常见的绊脚石是大写。标准文档类的 \chaptermark / \sectionmark 会先把标题送进 \MakeUppercase 再交给标记,所以 \leftmark 里装的本来就是「CHAPTER 1. INTRODUCTION」这样的全大写文字。想恢复原来的大小写,就用 fancyhdr 的 \nouppercase 包起来——它把参数放进一个让 \MakeUppercase 和 \uppercase 都失效的环境里排版。不过这种取消对内部一切有效,同一槽位里刻意写的大写也会被一并还原。若想彻底掌控页眉文字,就自己调用 \markboth / \markright,或者重新定义 \chaptermark。
% Chapter title on the left, page number on the right.
% \nouppercase undoes the \MakeUppercase applied by the class.
\fancyhead[L]{\nouppercase{\leftmark}}
\fancyhead[R]{\thepage}
% Or set the running-head text by hand, with no automatic updating.
\pagestyle{myheadings}
\markboth{Left-hand page text}{Right-hand page text}如何修正 Package fancyhdr Warning: \headheight is too small
这条警告是在说:装页眉的盒子比放进去的内容还矮。把 \headheight 加大到警告提示的数值,它就消失了。标准文档类把 \headheight 设为 12pt,而一条 0.4pt 的横线加上其上的行距就足以撑破——所以载入 fancyhdr 后第一次编译常常立刻看到它。消息里写明了所需高度,直接照抄 Make it at least … 后面那个数值即可。
加大的办法有两种:用 \setlength{\headheight}{15pt} 直接指定,或通过 geometry 的 headheight= 选项传入。两者都能让警告消失;但只要导言区里已有 geometry,就把这个值一并交给它更稳妥——\headheight 与正文高度、\topmargin 处在同一套算式中,事后只改其中一项,正文的纵向位置可能会挪位。若没有用 geometry,经典做法是在 \setlength 之后补一句 \addtolength{\topmargin}{-3pt} 之类,让总高保持不变——警告文本建议的正是这个调整。
% Either one of these is enough.
\setlength{\headheight}{15pt} % enlarge the header box directly
\addtolength{\topmargin}{-3pt} % ... and keep the vertical totals unchanged
% Or let geometry do the arithmetic for the whole page.
\usepackage[headheight=15pt]{geometry}把页码从 i, ii, iii 切换到 1, 2, 3(\pagenumbering)
写 \pagenumbering{roman},此后的页码就变成 i, ii, iii……;写 \pagenumbering{arabic} 又回到 1, 2, 3……。关键之处在于,这个命令不只是换格式,它还会 把页码计数器重置为 1。LaTeX 的定义开头就是 \global\c@page \@ne。于是「前置部分用罗马数字从 i 起、正文用阿拉伯数字从 1 起」这个书籍惯例,只需两行源码。
| 参数 | 输出 |
|---|---|
arabic | 阿拉伯数字:1, 2, 3 …(默认) |
roman | 小写罗马数字:i, ii, iii …(前置部分的惯例) |
Roman | 大写罗马数字:I, II, III … |
alph | 小写字母:a, b, c …。到第 27 页会以 ! LaTeX Error: Counter too large. 中断 |
Alph | 大写字母:A, B, C …。同样在 26 页之后耗尽 |
如果用的是 book 类,这两行其实已经替你写好了:\frontmatter 的定义里含有 \pagenumbering{roman},\mainmatter 里含有 \pagenumbering{arabic},你再写一遍就是把同一次切换做了两次(无害,但多余)。article 和 report 没有 \frontmatter,那里就得自己调用 \pagenumbering。想从任意数字起编,用 \setcounter{page}{7};想取出当前页码,用 \thepage。还有一个值得记住的陷阱:alph / Alph 只有 26 个字母够用,一旦排到第 27 页,编译就会以 ! LaTeX Error: Counter too large. 中断。
% book: \frontmatter and \mainmatter already switch the numbering.
\frontmatter % includes \pagenumbering{roman}
\tableofcontents
\mainmatter % includes \pagenumbering{arabic}
% article / report: no \frontmatter, so do it by hand.
\pagenumbering{roman} % i, ii, iii ... and the counter is reset to 1
\tableofcontents
\clearpage
\pagenumbering{arabic} % 1, 2, 3 ... counting starts over
\setcounter{page}{7} % or force any starting number从头到尾搭一套双面书籍页眉
把前面的零件拼进同一份导言区,就得到传统书籍的排布:页码在跨页外侧,章标题在偶数页内侧,节标题在奇数页内侧,页眉下有一条细线。章的首页是唯一由 \chapter 强行指定 plain 的地方,因此重新定义 \fancypagestyle{plain},把它也拉进同一套设计里。
\documentclass[twoside]{book}
\usepackage[headheight=15pt]{geometry}
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhf{} % clear all six slots first
\fancyhead[LE,RO]{\thepage} % page number on the outer edge
\fancyhead[RE]{\nouppercase{\leftmark}} % even page, inner edge: chapter
\fancyhead[LO]{\nouppercase{\rightmark}} % odd page, inner edge: section
\renewcommand{\headrulewidth}{0.4pt} % thin rule under the header
\renewcommand{\footrulewidth}{0pt} % no rule above the footer
\fancypagestyle{plain}{% % chapter openings, same design
\fancyhf{}%
\fancyfoot[C]{\thepage}%
\renewcommand{\headrulewidth}{0pt}%
}
\begin{document}
\chapter{Introduction}
\section{Background}
Body text goes here. From the next page on, the running head shows
the chapter, the section and the page number.
\end{document}最后给一条判断的准绳。单面的短文档只要页脚有个页码就够了,那就保持 \pagestyle{plain},什么都别加。 只想让章、节标题出现在页眉,\pagestyle{headings} 就能办到。 当你开始想自己决定位置和字体时,才转向 fancyhdr。 按需要逐层引入,最终得到的导言区最经得起时间。还有一条容易忘的原则:页眉的存在是为了让读者知道自己在哪,所以放在上面的,通常「当前所在的章节」比「文档标题」更卖力。