Menu

HowTo_ChapterWithLines

How to put a horizontal line above and below chapter headings

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}

Page 1 und 3 of the example

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}

Page 1 and 3 of the example

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}

Page 1 and 3 of the example

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.

How the top line can intersect the chapter number

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:

  1. The box for the number remains, only no number is output.
  2. The box for the number is omitted.

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}

Seite 1 und 3 des Beispiels

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}

Seite 1 und 3 des Beispiels

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}

Seite 1 und 3 des Beispiels

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.


Related

Wiki (English): HowTo_Headings

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.