A requirement that can be found quite often is to add horizontal lines to chapter headings. For this the KOMA-Script classes scrbook
and scrreprt
offer several possible solutions. One possibility, which has been available for over twenty years, is to redefine the \chapterheadstartvskip
and \chapterheadendvskip
commands:
\documentclass{scrbook}
\usepackage{blindtext}
\usepackage{xpatch}
\xapptocmd{\chapterheadstartvskip}{%
{%
\setlength{\parskip}{0pt}%
\setlength{\parfillskip}{0pt plus 1fil}%
\noindent\rule[.3\baselineskip]{\linewidth}{1pt}\par
}\nobreak
}{%
\typeout{Horizontal line before chapter heading added.}%
}{%
\errmessage{Failed to patch \string\chapterheadstartvskip}%
}%
\xpretocmd{\chapterheadendvskip}{%
{%
\setlength{\parskip}{0pt}%
\setlength{\parfillskip}{0pt plus 1fil}%
\noindent\rule[-.3\baselineskip]{\linewidth}{1pt}\par
}\nobreak
}{%
\typeout{Horizontal line after chapter heading added.}%
}{%
\errmessage{Failed to patch \string\chapterheadendvskip}%
}%
\begin{document}
\tableofcontents
\blinddocument
\end{document}
Normally the two instructions are used to output the vertical distance before and after the chapter heading. Here, after outputting the top space in \chapterheadstartvskip
and before outputting the bottom space in \chapterheadendvskip
, the output of a line is patched into the two statements using the xpatch
package. Since at this point the document settings for \parindent
, \parskip
and \parfillskip
still apply, but the line is to be set across the entire width, at least \parskip
and \parfillskip
must be temporarily adjusted within a local group and any indentation must be prevented with \noindent
.
The method works for both numbered and unnumbered headers. It would also work when using option chapterprefix
and then inserting the top line as well above the prefix line.
The disadvantage of this method is that any call to \DeclareSectionCommand
or \RedeclareSectionCommand
to configure \chapter
will undo the change, because it will reset \chapterheadstartvskip
and \chapterheadendvskip
to the default definition.
Since KOMA-Script classes 3.19, however, there is another, better possibility with the \chapterlinesformat
and \chapterlineswithprefixformat
commands:
\documentclass{scrbook}
\usepackage{blindtext}
\makeatletter% because of using \@hangfrom
\renewcommand*{\chapterlinesformat}[3]{%
\Ifstr{#1}{chapter}{%
\rule[.3\baselineskip]{\linewidth}{1pt}\par\nobreak
}{}%
\@hangfrom{#2}{#3}%
\Ifstr{#1}{chapter}{%
\rule[.3\baselineskip]{\linewidth}{1pt}\par\nobreak
}{}%
}
\renewcommand*{\chapterlineswithprefixformat}[3]{%
\Ifstr{#1}{chapter}{%
\rule[.3\baselineskip]{\linewidth}{1pt}\par\nobreak
}{}%
#2#3%
\Ifstr{#1}{chapter}{%
\rule[.3\baselineskip]{\linewidth}{1pt}\par\nobreak
}{}%
}
\makeatother% because of \makeatletter
\begin{document}
\tableofcontents
\blinddocument
\end{document}
Here the lines are inserted directly in the output of the heading. Via \Ifstr
the change is restricted to chapter headings. In the concrete example this restriction would not be necessary, because only the chapter headings are set in the style chapter
. The restriction was made only in case the user defines other headings in this style.
It is not necessary to change \parskip
and \parfillskip
or to prevent paragraph indentation because the heading context is already active here. In this context there is neither paragraph spacing nor paragraph indentation and the last line of a paragraph may also be completely filled.
This solution also works with both numbered and unnumbered chapter headings. The redefinition of \chapterlineswithprefixformat
has also been made for the case where option chapterprefix
is used. In this case the top line still appears above the prefix line. However, it is often desired that the line first appears below the prefix line. Not infrequently, this is combined with the prefix line being right-justified instead of left-justified and the complete heading being set in upper case. All of this is easily possible by suitably redefining \chapterformat
and \chapterlineswithprefixformat
:
\documentclass[chapterprefix]{scrbook}
\usepackage{microtype}
\usepackage{blindtext}
\makeatletter% because of using \@hangfrom
\renewcommand*{\chapterlinesformat}[3]{%
\Ifstr{#1}{chapter}{%
\rule[.3\baselineskip]{\linewidth}{1pt}\par\nobreak
}{}%
\@hangfrom{\textsl{\MakeUppercase{#2}}}{\textsl{\MakeUppercase{#3}}}%
\Ifstr{#1}{chapter}{%
\rule[.3\baselineskip]{\linewidth}{1pt}\par\nobreak
}{}%
}
\renewcommand*{\chapterformat}{%
\IfUsePrefixLine{%
\textls{\MakeUppercase{\chapapp\nobreakspace\thechapter\autodot}}%
}{%
\thechapter\autodot\endskip
}%
}
\renewcommand*{\chapterlineswithprefixformat}[3]{%
\Ifstr{#1}{chapter}{%
\raggedleft
#2%
\rule[.3\baselineskip]{\linewidth}{1pt}\par\nobreak
\raggedchapter
\textls{\MakeUppercase{#3}}%
\rule[.3\baselineskip]{\linewidth}{1pt}\par\nobreak
}{#2#3}%
}
\makeatother% because of \makeatletter
\begin{document}
\tableofcontents
\blinddocument
\end{document}
The package microtype
is used in the example to achieve automatic letterspacing of capital letter. This is the only way I know of to achieve the necessary letterspacing with compensation at least reasonably well automatically. How well the possibility works, however, depends very much on the font used. For this reason, I take a fundamentally critical view of automatic capitalization.
The advantage of redefining \chapterformat
and \chapterlinesformat
resp. \chapterlineswithprefixformat
is that the change persists when chapter headings are reconfigured with \RedeclareSectionCommand
. For example, it is possible to change the distance between the prefix line and the horizonta line using the innerskip
option.
When adapting this solution for section, note that \sectionlinesformat
has four arguments instead of three. For more details, see Part II of the KOMA-Script manual or the German KOMA-Script book.
As an extension, it is also possible to imagine that the chapter number should be placed with a colored background on the upper of the two lines in such a way that the line intersects the box with the chapter number. For chapter headings without a number, two different variants are conceivable:
It may seem surprising that the first variant is the simpler one:
\documentclass{scrbook}
%\usepackage{microtype}
\usepackage{xcolor}
\renewcommand*{\chapterformat}{\thechapter}
\renewcommand*{\raggedchapter}{\raggedleft}
\setkomafont{chapter}{\LARGE}
\setkomafont{chapterprefix}{\Huge}
\newcommand*{\ChapterCase}[1]{#1}
%\newcommand*{\ChapterCase}[1]{\MakeUppercase{#1}}% grauenvoll / ugly
%\newcommand*{\ChapterCase}[1]{\MakeUppercase{\textls[75]{#1}}}% besser / better
\renewcommand*{\chapterlinesformat}[3]{% #1 = Ebenenname / chapter command name
% #2 = Nummer (oder leer) / number (or empty)
% #3 = Text / text
\rule[-\dp\strutbox]{\linewidth}{.4pt}%
\IfArgIsEmpty{#2}{%
\parbox[c][\dimexpr 1.5em+2\fboxsep]{0pt}{}\par\kern\fboxsep
}{%
\makebox[0pt][l]{%
\hspace{-\linewidth}\hspace{.5em}%
\colorbox{black}{%
\parbox[c][1.5em][c]{1.5em}{%
\centering
\textcolor{white}{%
\usekomafont{chapterprefix}{%
\strut #2%
}%
}%
\par
}%
}%
}%
}\par
\ChapterCase{\strut\ignorespaces #3}%
\rule[.5em]{\linewidth}{.4pt}\par\nobreak
}
\usepackage{mwe}
\begin{document}
\tableofcontents
\blinddocument
\end{document}
By the way, in the example we use \strut
twice so that the height and depth of the output is always the same regardless of the concrete text or number. The \strut
is a vertical line of zero width and the default height and depth of a text line. In contrast, individual characters may be less high or deep depending on their shape.
In the second variant, on the other hand, one must take into account that normally the box with the number has an effect on the vertical position of the heading itself. So if you want to nail that heading's position, you still have to occupy the space for the box. A possible solution would be:
\documentclass{scrbook}
%\usepackage{microtype}
\usepackage{xcolor}
\renewcommand*{\chapterformat}{\thechapter}
\renewcommand*{\raggedchapter}{\raggedleft}
\setkomafont{chapter}{\LARGE}
\setkomafont{chapterprefix}{\Huge}
\newcommand*{\ChapterCase}[1]{#1}
%\newcommand*{\ChapterCase}[1]{\MakeUppercase{#1}}% grauenvoll / ugly
%\newcommand*{\ChapterCase}[1]{\MakeUppercase{\textls[75]{#1}}}% besser / better
\renewcommand*{\chapterlinesformat}[3]{% #1 = Ebenenname / chapter command name
% #2 = Nummer (oder leer) / number (or empty)
% #3 = Text / text
\rule[-\dp\strutbox]{\linewidth}{.4pt}%
\IfArgIsEmpty{#2}{%
\parbox[c][\dimexpr 1.5em+2\fboxsep]{0pt}{}\par\kern\fboxsep
}{%
\makebox[0pt][l]{%
\hspace{-\linewidth}\hspace{.5em}%
\colorbox{black}{%
\parbox[c][1.5em][c]{1.5em}{%
\centering
\textcolor{white}{%
\usekomafont{chapterprefix}{%
\strut #2%
}%
}%
\par
}%
}%
}%
}\par
\ChapterCase{\strut\ignorespaces #3}%
\rule[.5em]{\linewidth}{.4pt}\par\nobreak
}
\usepackage{mwe}
\begin{document}
\tableofcontents
\blinddocument
\end{document}
An in the end much simpler method is to use \vphantom
. The statement pretends in the vertical that the corresponding material is present without actually outputting it. To avoid having to specify the content once for the case of numbering and once for the opposite case, you can simply put it in a box first, ignoring the fact that the number may be empty:
\documentclass{scrbook}
%\usepackage{microtype}
\usepackage{xcolor}
\renewcommand*{\chapterformat}{\thechapter}
\renewcommand*{\raggedchapter}{\raggedleft}
\setkomafont{chapter}{\LARGE}
\setkomafont{chapterprefix}{\Huge}
\newcommand*{\ChapterCase}[1]{#1}
%\newcommand*{\ChapterCase}[1]{\MakeUppercase{#1}}% grauenvoll / ugly
%\newcommand*{\ChapterCase}[1]{\MakeUppercase{\textls[75]{#1}}}% besser / better
\newsavebox\chapternumberbox
\renewcommand*{\chapterlinesformat}[3]{% #1 = Ebenenname / chapter command name
% #2 = Nummer (oder leer) / number (or empty)
% #3 = Text / text
\rule[-\dp\strutbox]{\linewidth}{.4pt}%
\sbox\chapternumberbox
{%
\makebox[0pt][l]{%
\hspace{-\linewidth}\hspace{.5em}%
\colorbox{black}{%
\parbox[c][1.5em][c]{1.5em}{%
\centering
\textcolor{white}{%
\usekomafont{chapterprefix}{%
\strut #2%
}%
}%
\par
}%
}%
}%
}%
\IfArgIsEmpty{#2}{%
\vphantom{\usebox\chapternumberbox}%
}{\usebox\chapternumberbox}%
\par
\ChapterCase{\strut\ignorespaces #3}%
\rule[.5em]{\linewidth}{.4pt}\par
}
\makeatother
\usepackage{mwe}
\begin{document}
\tableofcontents
\blinddocument
\end{document}
In the examples I have deliberately not included the alignment of the heading, the choice of font and similar things in the definition of \chapterlinesformat
, so that you can easily change such things. Furthermore, I have presented three variants for the case-sensitivity of the heading. The first one is the one I would choose. The second without letterpsaced capitals is the one I wouldn't recommend to anyone. The third one uses the package microtype
to implement at least some kind of automatic letter spacing, which however comes without correct balancing and therefore font-dependent is partly not much better.