# Using fixed space aroung headings to get text in sync with baseline grid

In order to make my text stay in sync with the baseline grid, I've set the vertical spacing before and after \section headings to integer multiples of \baselineskip (using the titlesec package). A \section heading, in this example, is preceded by exactly two, and followed by exactly one blank line (as suggested by Robert Bringhurst). TeX's vertical stretching and shrinking might have its advantages, but those are less relevant to this particular project, which consists of no vertical material but plain text and headings, and which requires proper grid-typesetting. Oh, and there's only one font size throughout the entire book.

Now, \subsection headings I'd like to be preceded by 1.5\baselineskip, and followed by 0.5\baselineskip. Consider the MWE below. Everything's fine as long as the start of a new \subsection doesn't coincide with a new page -- in which case the 1.5\baselineskip gets gobbled, causing the remaining text to fall out of sync with the grid. Of course, that's what you'd expect, but I'm wondering if there's a way to change it; to make 0.5 of these 1.5\baselineskip indigestible, in order to have the heading fall between two lines, but have the first line of the text be in sync again.

All I've come up with so far is a workaround, or rather a somewhat dirty hack, which inserts a thick white rule before the heading. Besides being somewhat dirty, though, it has the drawback of (1) relying on a number determined by trial & error (0.6\baselineskip), which might be wrong when other factors change and (2) not working properly when a subsection does not start at the top of a new page (it un-syncs the text on page 3).

Any other ideas are appreciated, thanks in advance! They don't have to rely on titlesec by the way, which is something I've been living without so far.

\documentclass[paper=a5,pagesize]{scrartcl}
\usepackage{blindtext,xcolor,tikz,eso-pic,titlesec}

\setkomafont{section}{\normalsize}

% baseline grid
\AtTextLowerLeft{
\begin{tikzpicture}[overlay,remember picture]%
\draw[red!10!white,thin]%
(current page.south west) grid[step=\baselineskip]%
(current page.north east);%
\end{tikzpicture}%
}%
}

\titlespacing*{\section}{0em}{2\baselineskip}{\baselineskip}
\titlespacing*{\subsection}{0em}{1.5\baselineskip}{0.5\baselineskip}
\titlespacing*{\subsubsection}{0em}{\baselineskip}{0em}

%% workaround
%\titlespacing*{\subsection}{0em}{1\baselineskip}{0.5\baselineskip}
%\titleformat{\subsection}{\sectfont{\color{white}\titlerule[0.6\baselineskip]}}{\thesubsection}{1ex}{}

\begin{document}
\section{Lorem Ipsum}
\Blindtext
\subsection{Lorem Ipsum}
\Blindtext\newpage
\subsection{Lorem Ipsum}
\Blindtext
\subsubsection{Lorem Ipsum}
\Blindtext
\end{document}


# edit/update

What follows is an second improvement of the workaround (but a workaround it remains nevertheless), now in a complete MWE:

\documentclass[paper=a5,pagesize]{scrartcl}
\usepackage{xcolor,tikz,eso-pic,titlesec,blindtext}
\setkomafont{section}{\normalfont}
\setkomafont{subsection}{\normalfont}
\setkomafont{subsubsection}{\normalfont}

% baseline grid
\AtTextLowerLeft{
\begin{tikzpicture}[overlay,remember picture]%
\draw[red!10!white,thin]%
(current page.south west) grid[step=\baselineskip]%
(current page.north east);%
\end{tikzpicture}%
}%
}

\titlespacing*{\section}{0em}{2\baselineskip}{\baselineskip}
\titlespacing*{\subsection}{0em}{1\baselineskip}{0.5\baselineskip}
\titlespacing*{\subsubsection}{0em}{\baselineskip}{0em}

%% workaround
\titleformat{\subsection}{\vspace{0.85\baselineskip}\vspace*{-0.35\baselineskip}}{\thesubsection}{1ex}{}

\begin{document}
\section{Lorem Ipsum}
\Blindtext
\subsection{Lorem Ipsum}
\Blindtext\newpage
\subsection{Lorem Ipsum}
\Blindtext
\subsubsection{Lorem Ipsum}
\Blindtext
\end{document}


## update, Feb 21

(in reply to Hendrik's answer) sorry, I was a bit too sloppy in testing your solution, Hendrik. The \topskip trick does work fine if the page break that comes before the new subsection is a manual one (as in the example), but if the page breaks automatically (as it does in real life when the page preceding the heading is full), the heading is on the first baseline rather than offset by 0.5\baselineskip -- the space gets eaten as usual. See here:

\begin{document}
\section{Lorem Ipsum}
\Blindtext
\subsection{Lorem Ipsum}
\Blindtext\newpage
\subsection{Lorem Ipsum}
\Blindtext
\subsection{Lorem Ipsum}
\blindtext\blindtext\blindtext\blindtext
\subsection{Lorem Ipsum} % <---------------- !
\blindtext
\end{document}


I'm not saying the \topskip approach is a bad idea; I currently just don't have a idea how to improve it.

-

(Posting this as a separate answer as it offers a completely different solution.)

There's a very simple solution to your problem that should also work in more complex situations involving footnotes and other stuff: put one \baselineskip before and after the subsection heading (so that everything is on the grid), and use \raisebox to lower both the number and the title by 0.5\baselineskip.

Note the optional arguments [0pt][0pt] to \raisebox: they make the height and in particular the depth of the heading zero so that the subsequent lines stay on the grid.

\documentclass[paper=a5,pagesize]{scrartcl}
\usepackage{blindtext,xcolor,tikz,eso-pic,titlesec}
\setkomafont{section}{\normalsize}
% baseline grid
\AtTextLowerLeft{
\begin{tikzpicture}[overlay,remember picture]%
\draw[red!10!white,very thin]%
(current page.south west) grid[step=\baselineskip]%
(current page.north east);%
\end{tikzpicture}%
}%
}
\titlespacing*{\section}{0em}{2\baselineskip}{\baselineskip}
\titlespacing*{\subsection}{0em}{\baselineskip}{\baselineskip}
\titlespacing*{\subsubsection}{0em}{\baselineskip}{0em}
\titleformat{\subsection}
{\sffamily\bfseries}
{\raisebox{-0.5\baselineskip}[0pt][0pt]{\thesubsection}}
{1ex}
{\raisebox{-0.5\baselineskip}[0pt][0pt]} % raise the title
\begin{document}
\section{Lorem Ipsum}
\Blindtext\newpage
\subsection{Lorem Ipsum}
\Blindtext
\subsection{Lorem Ipsum}
\blindtext\blindtext\blindtext\blindtext
\subsection{Lorem Ipsum} % Works now!
\blindtext
\end{document}

-
wow, that's so simple it's no surprise I wasn't able to come up with it myself. I can confirm this one works in even those situations in which the other fix failed. –  Nils L Mar 5 at 11:50

The idea of my solution is to increase \topskip by 0.5\baselineskip for \subsections. If this happens at the top of a page, it'll move the title of the subsection down by 0.5\baselineskip as desired. It has no effect if the \subsection starts somewhere in the middle of a page: TeX looks at \topskip only when the first box is put onto the page. Moreover, the increase of \topskip is local, so it doesn't affect later pages.

To make the idea work, we have to look where on the page we are: when we're near the bottom, a \pagebreak has to be issued before the new subsection title. The point is that TeX usually "digests" more than enough material for one page before it decides where to break the page. Thus, it could happen that the (local!) \topskip change is already disgested before the pagebreak is performed. To prevent this, we have to manually break the page if there's only space for three lines left of the page.

Now the code below works after explicit \pagebreaks as well as at "natural" pagebreaks.

\documentclass[paper=a5,pagesize]{scrartcl}
\usepackage{blindtext,xcolor,tikz,eso-pic,titlesec}
\setkomafont{section}{\normalsize}
% baseline grid
\AtTextLowerLeft{
\begin{tikzpicture}[overlay,remember picture]%
\draw[red!10!white,very thin]%
(current page.south west) grid[step=\baselineskip]%
(current page.north east);%
\end{tikzpicture}%
}%
}
\titlespacing*{\section}{0em}{2\baselineskip}{\baselineskip}
\titlespacing*{\subsection}{0em}{1.5\baselineskip}{0.5\baselineskip}
\titlespacing*{\subsubsection}{0em}{\baselineskip}{0em}
\makeatletter
\titleformat{\subsection}
{\dimen@=\pagetotal
\ifdim\dimen@>\pagegoal\pagebreak\fi
\sffamily\bfseries}
{\thesubsection}{1ex}{}
\makeatother
\begin{document}
\section{Lorem Ipsum}
\Blindtext\newpage
\subsection{Lorem Ipsum}
\Blindtext
\subsection{Lorem Ipsum}
\blindtext\blindtext\blindtext\blindtext
\subsection{Lorem Ipsum} % Works now!
\blindtext
\end{document}

-
thanks! I see your point about the side effects (as it effectively changes the type area), but that's the problem with my hack as well. The good thing about yours is we get avoid those odd \baselineskip factors. I'll do some experiments with it, wait for a few more comments before marking it answered. –  Nils L Feb 17 at 11:16
@Nils: Well, yes, it changes the type area, but hopefully only in cases where you want it. –  Hendrik Vogt Feb 17 at 13:31
after some days of testing in larger documents, I haven't noticed any side effects. So far, the type area only changes where I want it :) –  Nils L Feb 20 at 15:31
@Nils: Great, thanks for letting me know! –  Hendrik Vogt Feb 20 at 15:43
@Nils: Yes, you got it. I added some explanation to my answer - better? –  Hendrik Vogt Feb 22 at 12:46

An alternative scheme is to arrange that only 1 of the 1.5\baselineskip glue above the heading is discardable.

This modifies things so that above a subsection there is an empty line with 1 (discardable) worth of baselineskip glue (it may be less than baselineskip, depending on the depth of teh previous item. Following the the line with the null box is a penalty to prevent a line break at that point and then half a baseline glue to the actual heading. This means that even at the top of the page you get a null line and half a baseline skip.

\documentclass[paper=a5,pagesize]{scrartcl}
\usepackage{blindtext,xcolor,tikz,eso-pic,titlesec}

\setkomafont{section}{\normalsize}

% baseline grid
\AtTextLowerLeft{
\begin{tikzpicture}[overlay,remember picture]%
\draw[red!10!white,thin]%
(current page.south west) grid[step=\baselineskip]%
(current page.north east);%
\end{tikzpicture}%
}%
}

\titlespacing*{\section}{0em}{2\baselineskip}{\baselineskip}
\titlespacing*{\subsection}{0em}{.5\baselineskip}{0.5\baselineskip}
\titlespacing*{\subsubsection}{0em}{\baselineskip}{0em}

%% workaround
%\titlespacing*{\subsection}{0em}{1\baselineskip}{0.5\baselineskip}
%\titleformat{\subsection}{\sectfont{\color{white}\titlerule[0.6\baselineskip]}}{\thesubsection}{1ex}{}

\makeatletter
\def\xsubsection{subsection}
\let\oldttl@straight@ii\ttl@straight@ii
\def\ttl@straight@ii #1#2#3#4#5#6#7{%
\def\tmp{#6}%
\ifx\tmp\xsubsection
\null\nobreak
\fi
\oldttl@straight@ii{#1}{#2}{#3}{#4}{#5}{#6}{#7}}
\begin{document}
\section{Lorem Ipsum}
\Blindtext
\subsection{Lorem Ipsum}
\Blindtext\newpage
{\tracingall
\subsection{Lorem Ipsum}}
\Blindtext
\subsubsection{Lorem Ipsum}
\Blindtext
\end{document}

-
looks good! I'm glad to have two suggestions now that I can compared. Will do some thorough testing today and tomorrow. –  Nils L Feb 26 at 10:04
here's some results from my tests. Your code does make a subsection heading fall between two lines even on a new page, as intended. However, the vertical offset is too large by 1\baselineskip. I tried to fix it (which I think is possible), but I don't understand enough of what's going on in your modification. What I find more concerning is this side effect: every page in which a new subsection starts (at the top or further down) ends prematurely -- one line too early. This problem occurs reliably even when lots of more subsections are added. See also here. –  Nils L Feb 28 at 9:20
@NilsL Hmm that sounds like a bug or two:-) This method can be made to work but sounds like I didn't get the implementation quite right, I may get back to this but not sure when (probably not in the next 21 hours:-) –  David Carlisle Feb 28 at 9:37
thanks, and don't worry about the time frame -- it's not that I have to hand in my book in 21 hours (or, for that matter, with headings offset by .5\baselineskip) :) –  Nils L Feb 28 at 10:43
»a bug or two« -- after some more testing, it seems bug number two simply consists in your modification overriding scrreprt's font settings for \subsection headings. Your code, as it is, produces those headings at larger-than-\normalsize. The problem is easily fixed by explicitly calling \setkomafont{subsection}{\normalsize} after or before [!?] your modification. Here's the code from your post with this fix included, plus some more lorem ipsum. Only problem #1 seems to persist, cf. page 6 of the output. –  Nils L Feb 28 at 13:46
I suggest that you take a look at the package grid, by River Valley Technologies. That package redefine a lot of internal rubber to achieve what you are trying to do.
grid packages helps to enable grid typesetting (i.e., vertically aligning lines of text in adjacent columns) in double column documents in LaTeX.
yes, there's grid, and there's also gridset BTW. I've tinkered with both repeatedly over the past years. grid I abandoned, though, for it's aimed at double-col layouts. But gridset has proven pretty helpful. It simply provides \vskipnextgrid, which puts what follows it back in sync with the grid. So that's something you might use after a big chapter heading, a table, a list, etc. Unfortunately, even gridset is no help in this case, as the problem is not getting back on the grid after getting off -- but getting off, deliberately and orderly, in the first place. –  Nils L Feb 26 at 10:02
I wouldn't mind you leaving it there for people who stumble upon this. As for your point about ConTeXt: basically, full ACK, but in this particular case (we're talking about a very simply-structured document) I'd say the difference between default behavior and the behavior I'm trying to achieve (an additional .5\baselineskip before a heading on a new page) is too small to justify a move to an entirely different platform. That said, I'd probably be a ConTeXt user already if it supported biblatex or provided an equivalent. That's the only thing that's keeping me from switching. –  Nils L Feb 26 at 13:29