LaTeX教程(009)- LaTeX \LaTeX LATEX文档结构(09)
本篇是讲解 titlesec
包的最后一篇。
在第007篇中,我们讲了 drop
和 wrap
形状的区别,drop
使用的是固定宽度,即在 \titlespacing
中的 left-sep
参数输入的长度数值会被指定为 drop
形状标题的固定宽度。而对 wrap
形状的标题来说,它是标题的最大宽度。wrap
标题会在不超过最大宽度的前提下,优化标题的断行,最后将标题行最长的一行视作整个标题占据的宽度。这个宽度的数值会存储在 \titlewidth
中。通过在调用 titlesec
包时指定 calcwidth
选项,这一机制可以扩展到其他形状,然后在 \titleformat
的参数中根据需要使用 \titlewidth
命令。
我们上一篇讲了一个 \rule
命令,在 titlesec
包中,也提供了一个替代命令 \titlerule
,它不带任何参数时,会生成一个高度(这里指厚度)为0.4pt,横跨整个标题栏的线段(要减去 \titlespacing
指定的间距,也就是说,它和标题的最大宽度等宽)。有一个可选参数可以指定线段的高度(厚度)。我们用一个例子演示一下:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage[calcwidth]{titlesec}
\usepackage{kantlipsum}
\begin{document}
\titleformat{\section}[frame]{}{\footnotesize SECTION \thesection}{0.2cm}{\bfseries\filcenter}
\titlespacing{\section}{2cm}{0.5cm}{0.2cm}[2cm]
\section{This is a section}
\titlerule % 生成一个高度为0.4pt,横跨整个标题栏的线段
\vspace*{3pt} % 生成3pt的垂直距离
\titlerule[2pt]
\vspace*{3pt} % 生成一个高度为3pt,横跨整个标题栏的线段
\kant[1]
\end{document}
编译:
该命令的星号形式 \titlerule*
用来生成一条引导线,它是一条看不见的线段。它有一个可选参数和一个必选参数,必选参数中放置一些文本。引导线用来引导文本的排列,而可选参数可以修改文本之间的间隔。这些文本会在条线段上重复排列。默认情况下,它们以自然宽度排列,而我们可以通过指定可选参数来修改文本之间的间隔。注意,这里的间隔是指文本开头到下一个重复的文本开头的距离,这意味着,如果这个间隔不足够大,文本可能会重叠:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage[calcwidth]{titlesec}
\usepackage{kantlipsum}
\begin{document}
\titleformat{\section}[frame]{}{\footnotesize SECTION \thesection}{0.2cm}{\bfseries\filcenter}
\titlespacing{\section}{2cm}{0.5cm}{0.2cm}[2cm]
\section{This is a section}
\titlerule
\vspace*{3pt}
\titlerule*{\LaTeX}
\vspace*{3pt}
\titlerule
\vspace*{3pt}
\titlerule*[0.3cm]{\LaTeX}
\vspace*{3pt}
\titlerule
\vspace*{3pt}
\titlerule*[1.5cm]{\LaTeX}
\vspace*{3pt}
\kant[1]
\end{document}
编译:
\titleline
生成一个行,它实际上是一个横跨整个标题栏的(减去 \titlespacing
指定的间距)水平盒子。它有一个可选参数和一个必选参数。必选参数中是一些要排版的材料,如文本等。可选参数指定这此材料的对齐方式,如 l
左对齐,r
右对齐,c
居中对齐,s
分散对齐。它的星号形式的变体 \titleline*
的可选参数的作用和 \titleline
基本相同,不同的是 \titleline*
将这些材料的排版在一个宽度为 \titlewidth
的盒子中(因此可能需要在这个参数中添加弹性空间,并且调用 titlesec
包时使用 calcwidth
选项来确保 \titlewidth
的值是正确的),这个盒子再被放置到主盒子中。
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{kantlipsum}
\usepackage[noindentafter,calcwidth]{titlesec}
\begin{document}
\titleformat{\section}[display] {\filright\normalfont\bfseries\sffamily}{\titleline[r]{Section \Huge\thesection}}{1ex}{\titleline*[l]{\titlerule[1pt]}\vspace{1pt}\titleline*[l]{\titlerule[2pt]}\vspace{2pt}}[{\titleline*[l]{\titlerule*{\tiny\LaTeX}}}]
\titlespacing{\section}{1pc}{*3}{*2}
\section{Rules and Leaders}
Note that the last \verb=\titleline*= is surrounded by braces. Without them its optional argument would prematurely end the outer optional argument of \verb=\titleformat=.
\end{document}
编译:
标准
LaTeX
\LaTeX
LATEX认为,在标题之前的空白处是一个很好的断页位置,除非该标题前面也是一个标题。
LaTeX
\LaTeX
LATEX为每一处都设置了一个断页的penalty
值 。penalty
是惩罚,损失的意思。一个地方的penalty
值越大,在这个地方断页的可能性(优先级)就越低。相反,一个地方的penalty
值越小,\LaTeX
就越会认为这是一个好的断页位置。在很多的文档类中,标题前面的空白处断页的penalty
值是-300
,它被存储在内部计数器\@secpenalty
中。它是一个负数,这意味着
LaTeX
\LaTeX
LATEX十分推荐在此处断页。所有标题前面的空白处断页的penalty
值都相同,所以很少有修改它的必要。然而,使用了titlesec
包,可以更精细的控制它。我们可以通过定义\<name>break
来改变与标题有关的断页行为,其中<name>
指划分命令的名称。例如,我们可以定义\sectionbreak
:
\newcommand{\sectionbreak}{\clearpage}
这将导致section
标题始终出现在页面的顶部,而所有的待处理的浮动体将首先被排版。我们做个演示:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titlesec}
\begin{document}
\titleformat{\section}[frame]{}{SECTION \thesection}{1ex}{\filcenter}
\titlespacing{\section}{1pc}{*3}{*2}
\newcommand{\sectionbreak}{\clearpage}
some text ......
\section{A section}
some test ......
\section{A section}
\end{document}
出于篇幅原因,编译结果我们仅用文字描述一下:
第1页仅有一行文字some text......
,该页面的其余部分均是空白。第2页是一个section
的标题,且位于页面的顶部(就像chapter
标题那样),后面紧跟一行文字some text......
,其余部分均是空白。第3页仍是一个section
的标题,其余部分均是空白。
但是,如果我们将两个连续的标题放在一起,即两个标题之间的文本去掉,就会看到两个标题出现在同一个页面中的情况。这是因为section
是标题类型不是top
。这里我们先简单介绍一下top
和page
类型。top
类型的标题和chapter
类似,它从新的一页开始,并且默认情况下,它只在奇数页上(书的右手页)。而page
类标的标题就像part
标题,它不仅从新的一页开始(默认是右手页),并且会独占一页(默认情况下是一页纸的正反两面)。我们可以用\titleclass
命令来改变标题的类型。例如:
\titleclass{\section}{top}
命令将section
标题指定为top
类。
标题的断页方式设置除了\clearpage
之外还有\cleardoublepage
,在讲这两个命令的区别之前,我们先介绍一下两个文档类型的选项,openright
和openany
。如果我们在\documentclass
命令后面指定可选参数openright
,那么就意味着该文档是双页的(有左手页和右手页)。如果指定了openany
,就意味着文档是单页的。book
类默认是双页的。在双页文档中,top
类标题和page
类标题默认只从文档的右手页开始; 在单页文档中,它们会从下一个页码开始,而不管该页是不是奇数页。
那么\clearpage
和\cleardoublepage
的区别是什么呢? \clearpage
在放置标题之前,用空白将当前页面的剩余空间填满,将标题放入下一个页面。单页文档中的chapter
和part
标题(如果有的话)的断页方式默认就是\clearpage
。\cleardoublepage
以一个奇数页和下一个偶数页的组合(一页纸的正反面)为基本单位,在放置标题之前,将当前的整页纸的剩余部分用空白填满,将标题放到下一个奇数页上。双页文档中的chapter
和part
标题的断页方式就是\cleardoublepage
。
我们可以改变这一行为,例如,我们可以在双页文档中将chapter
标题的断页方式设置为\clearpage
:
\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titlesec}
\begin{document}
\titleformat{\chapter}[frame]{}{CHAPTER \thechapter}{1ex}{\filcenter}
% 使用`\titleformat`重定义chapter类型
\titlespacing{\chapter}{1pc}{*3}{*2}
\titleclass{\chapter}{top}
% 重新指定标题类型
\newcommand{\chapterbreak}{\clearpage}
\chapter{A chapter}
\chapter{Chapter two}
\end{document}
对于在改变类型的标题,我们最好使用\titleformat
重定义它们(否则使用\titleclass
定义类型时会报错),并且在重定义后,再重新指定标题类型。
编译结果中我们可以看第1页中是chapter1,第2页就是chapter2。关于标题的类型的定义,我们下面会再讲。其他的标题我们也可以这样去设置,这里不重复演示。
默认情况下,标题出现在页面的顶部时,我们定义在标题上方的垂直空间会消失。如果在某些布局中,我们不想让它消失,那么可以通过如下方式实现:
\newcommand\sectionbreak{\addpenalty{-300}\vspace*{0pt}}
\addpenalty{-300}
命令将标题上方的断点指定为一个penalty
值为-300的断点,后面跟着一个不能消失的长度为0的垂直空间。如果在此处断页,那么标题前面的空间也将出现在页面的顶部。
对于出现在新页面上的标题,我们可能需要特殊的样式; 例如,如果我们想让\chapter
标题所在的页面不出现页眉和页码,就可以使用:
\assignpagestyle{\chapter}{empty}
如果我们不进行任何设置,那么默认情况下是plain
,而不是empty
。该命令对所有的top
和page
类标题都有效,我们也可以将其他标题设置成这样,只需要在该命令的前面先将要设置的标题的类型改成top
或者page
。
带有前提条件的布局
到目前为止,我们已经知道的如何使用\titleformat
和\titlespacing
为标题定义固定的布局。而titlesec
还可以定义带条件的布局,例如我们可以为奇数页和偶数页生成不同的布局,可以为有编号标题和无编号的标题(星号形式的标题)生成不同的布局。
这是通过在\titleformat
和\titlespacing
的第一个参数中使用键值对(keyword-value)来实现的。我们之前使用的语法形式\titleformat{\section}...
实际上是一种缩写,它的完全形式是titleformat{name=\section}...
。可用的键除了name
,还有page
,值为odd(奇数)或even(偶数),以及numberless
,是否是无编号的标题,无编号则值为true,有编号则为false。
但是要注意,判断page
页码奇偶的方式只对双页文档有效,单页文档不分左手页和右手页(注意book
类默认是双页文档)。我们用一个例子演示一下:
\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{kantlipsum}
\usepackage{titlesec}
\begin{document}
\tableofcontents
\titleformat{name=\section,page=odd}[block]{\normalfont\bfseries}{\thesection.}{6pt}{\itshape\filleft}
% 使section标题在左手页居左,在右手页居右。
\titleformat{name=\section,page=even}[block]{\normalfont\bfseries}{\thesection.}{6pt}{\itshape\filright}
\chapter{A chapter}
\kant[1]
\kant[1]
\section{A Head}
\kant[1]
\kant[4]
\section{Another}
\kant[2]
\end{document}
编译:
这里要注意调整一下你用以预览PDF的软件,使用书籍视图预览,将第一页单独放在右边。这样才能保证后面的奇数页(右手页)都在右边。
我们用一个例子演示一下numberless
的使用放式:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\usepackage{titlesec}
\begin{document}
\titleformat{name=\section}[block]{\normalfont\bfseries}{\thesection.}{6pt}{\filright}
% 上述定义作用于所有section标题
\titleformat{name=\section,numberless=true}[block]{\normalfont}{---}{12pt}{\itshape\filcenter}
% 上述定义仅作用于无编号的标题,遇到无编号的标题时,它会覆盖掉第一个定义
\section{A Head}
Some text to fill the page. Some text to fill the page.
\section*{Another}
Some text to fill this line.
\end{document}
编译:
不管是对于页码的判断还是对于编号的判断,如果我们不加判断,则定义会对所有指定的标题生效。而加了判断的定义,则会在遇到满足判断的标题时覆盖掉已有的定义。
改变标题的层级(类型)
前面我们知道使用\titleclass
命令可以改变标题的类型,实际上这个命令有三种形式:
\titleclass{cmd}{class}
\titleclass{cmd}{class}[parent-level-cmd]
\titleclass{cmd}[start-level]{class} % 加载包时指定loadonly选项
标题的类别(class
)也有三种,除了我们前面讲过的page
类和top
类,所有其他标题我们都用straight
类表示。
我们前面的例子中演示过,使用第一种形式(不带任何选项)可以直接为某个标题指定类别:
\titleclass{\section}{top}
但是要注意,对于任何标题命令,在改变它的类型之前,最好使用\titleformat
重定义它,否则很可能会报错。
第二种形式可以在parent-level-cmd
标题的下插入一个新的标题层级,而原本比parent-level-cmd
标题级别更低的所有标题均下降一个级别。例如:
\titleclass\subchapter{straight}[\chapter]
在\chapter
和\section
之间插入一个新的标题\subchapter
。但是这个声明没有为\subchapter
标题定义任何布局,也没有定义它的计数器,设计它的编号等。这些都需要另外的工作来完成:
\titleformat{\subchapter}{..}...
\titlespacing{\subchapter}{..}...
\newcounter{subchapter}
\renewcommand\thesubchapter{\thechapter.\arabic{subchapter}}
\renewcommand\thesection{\thesubchapter.\arabic{section}}
标题编号的定义结构我们在004篇详细讲过,不熟悉的话可以回顾一下。这里直接用一个例子演示一下:
\documentclass{book}
\usepackage[a5paper,margin=1in]{geometry}
% \usepackage{kantlipsum}
\usepackage{titlesec}
\begin{document}
% 定义一个新的层级的命令\subchapter
\titleclass\subchapter{straight}[\chapter]
% 定义它的计数器
\newcounter{subchapter}
% 定义被\subchapter的编号
\renewcommand\thesubchapter{\thechapter.\arabic{subchapter}}
% 重定义\section的编号,使\subchapter嵌入其中
\renewcommand\thesection{\thesubchapter.\arabic{section}}
% 定义\subchapter标题的样式
\titleformat{\subchapter}[block]{\fontsize{20.74pt}{20.74pt}\bfseries}{\thesubchapter}{12pt}{\filright}
\titlespacing{\subchapter}{0pc}{*3}{*2}
\chapter{A chapter}
\subchapter{A subchapter}
\section{A section}
some text
\section{Another section}
some text
\end{document}
编译:
第三种形式几乎不会用到,只有在你想要从头开始构建标题结构时——例如,你想要设计一个全新的文档类,而这个类不是基于任何标准类时——才会用到这一形式。这种情况下,包不会解释现有的标题命令并提取它们的布局。然后就可以构建标题命令了,如下例所示:
\newcounter{Ahead}
\newcounter{Bhead}
\newcounter{Chead}
\renewcommand\theBhead{\theAhead-\arabic{Bhead}}
\renewcommand\theChead{\theBhead-\arabic{Chead}}
\titleformat{name=\Ahead}{..}...
\titlespacing{name=\Ahead}{..}...
\titleformat{name=\Bhead}{..}...
...
根据不同的文档类,起始级别(start-level
)通常是0
或-1
(若不熟悉回顾一下003篇),一个文档类中,应该恰好有一个标题的声明需要用到这个参数。
关注【年轻人 你渴望力量么】