As you have noted, ex
(and em
) lengths are relative to the currently used fonts. The reason for this depends on the application. In your instance it makes sense using a font size-specific length, since the typesetting the sectional heading may be different depending on whether the document is processed using 10pt
, 11pt
or 12pt
(or, for that matter, any other font size) as \normalfont
. For example, using absolute lengths (like pt
, bp
or pc
, for example) may cause the gap between section headings and text to seem too small, or too large, if the font size is changed. The example below a font-based skip of 1em
between a pseudo-section heading is replaced by a fixed-width 11.5pt
skip (in 10pt
, 1em
or roughly 11.5pt
, see the TeX Book, p 60):
\documentclass{article}
\begin{document}
\bfseries% For bold font
{\normalfont Font-based skip of \verb!1em!} \par \medskip
\newcommand{\myskip}{\unskip\rule[0.5ex]{1em}{1pt}\ignorespaces}
{\normalsize 1 \myskip A section \par}%
{\large 1 \myskip A section \par}%
{\Large 1 \myskip A section \par}%
{\LARGE 1 \myskip A section \par}%
{\Huge 1 \myskip A section \par}%
\bigskip \hrulefill \bigskip
{\normalfont Fixed-width skip of \verb!11.5pt!} \par \medskip
\renewcommand{\myskip}{\unskip\rule[0.5ex]{11.5pt}{1pt}\ignorespaces}
{\normalsize 1 \myskip A section \par}%
{\large 1 \myskip A section \par}%
{\Large 1 \myskip A section \par}%
{\LARGE 1 \myskip A section \par}%
{\Huge 1 \myskip A section \par}%
\end{document}
Since I am not entirely sure of your sectional intent (that almost came out wrong), here's a suggestion when it comes to page-breaking woes. The needspace
package provides \needspace{<len>}
that issues a \break
if there is less than <len>
space available on the page. And, the code is not very complicated. Here is a modified version, now taking 3 arguments for the sake of this discussion:
\makeatletter
% \needspace{<len>}{<NOT enough space>}{<enough space>}
\newcommand{\needspace}[3]{\par \penalty-100\begingroup
\setlength{\dimen@}{#1}%
\dimen@ii\pagegoal \advance\dimen@ii-\pagetotal
\ifdim \dimen@>\dimen@ii% execute the following if there IS NOT enough space on page
\ifdim \dimen@ii>\z@
\vfil
\fi
\break
#2% <NOT enough space>
\else% execute the following if there IS enough space on page
#3% <enough space>
\fi\endgroup}
\makeatother
It would be possible to redefine \section
so as to use the above \needspace
and condition on the type of \@startsection
that should be called.
Yes, this is possible if you are prepared to accept a certain level of false positives. Basically for both cases special penalties are used by TeX and those can be recognized in the output routine. So my code below sets the value for \widowpenalty
to 151 and \clubpenalty
(orphans) to 152 (the LaTeX default is 150). The we use the following code:
\documentclass %[twocolumn]
{article}
\clubpenalty=152
\widowpenalty=153
% we want to know if we are on first or second column in a 2 column document
\makeatletter
\def\oncol{\if@twocolumn \space \if@firstcolumn (first \else (second \fi column)\fi}
\makeatletter
% check if the output penalty was due to orphan or widow or both
\def\testforwidowsandorphans{%
\ifnum\outputpenalty=153
\typeout{*** Widow on page \thepage \oncol}%
\else
\ifnum\outputpenalty=152
\typeout{*** Orphan on page \thepage \oncol}%
\else
\ifnum\outputpenalty=305
\typeout{*** Orphan and Widow on page \thepage \oncol}%
\fi
\fi
\fi
}
% execute this code at the very beginning of the OR
\toks0=\output
\output\expandafter{\expandafter\testforwidowsandorphans
\the\toks0}
\newcommand\stupidpara{First line\\second line\\and final line\par}
\newcommand\verystupidpara{First line\\and final one\par}
\setlength\textheight{5\baselineskip}
\begin{document}
\stupidpara\stupidpara\stupidpara\stupidpara
\verystupidpara\verystupidpara\verystupidpara\verystupidpara
\end{document}
Basically we test if the \outputpenalty
that triggered the page is either 152 or 153 or 305, ie the sum of it (which would be the case if a two line paragraph is broken).
That will give us the output:
*** Widow on page 1
[1]
*** Orphan on page 2
[2]
*** Orphan and Widow on page 3
and if we typeset the same document in twocolumn mode we get
*** Widow on page 1 (first column)
*** Orphan on page 1 (second column)
[1]
*** Orphan and Widow on page 2 (first column)
You may find that other page breaks produce the same penalties (which then gives you false positives) so chosing the initial values right is essential. Of course you could use 150 and not distinguish between widow and orphan.
Final note: one should probably also add \displaywidowpenalty
into the test (the default here is 50 in LaTeX and instead of a simple \typeout
one could think of a more elaborate output, but this is syntactic sugar.
Small update
As remarked by David Carlisle elsewhere it is better not to use 151 (as I did initially for the \clubpenalty
) as standard LaTeX uses 151 for \pagebreak[2]
so we would get some unnecessary false positives. Of course, if any of such default values are changed the above code would need to change too.
Also worth noting: changing the penalties even by only such small amounts means that the break behavior of your document could get altered, i.e., it may break differently after you added that code. As this version only adds warnings it is therefore best to keep using it all the time and not make the mistake of removing it just before "final" run after having corrected all problems it reported. It may just mean that afterwards you see new breaks --- unlikely but not impossible!.
Now available as a package
A much extended version of the above code is now available on CTAN as the package widows-and-orphans
. It automatically calculates the penalty values to make everything unique and detectible and besides widows and orphans it also detects hyphenation across column or page boundaries and math displays that got separated from the preceding text (in case that is allowed in the document).
Next Tugboat will contain an article that discusses various ways to fix such issues. I will also put it up soon at https://latex-project.org/publications
Best Answer
In a book like the one you are writing that primarily deals with textual information, the TeX engine has to balance two conflicting constraints.
If the
baselineskip
is set at a fixed size - which is the norm - the page can only contain so many multiples of this, say 30 lines of text. Depending on the write up TeX will have to decide between two bad choices, either not to achieve a flush at bottom layout or to accept a widow or an orphan and in most instances it will opt for the latter. Having had a look at the links you provided, your book only contains text and here lies the problem.For a page that contains a lot of equations, figures or sections there is normally adequate glue allowed by LaTeX to adjust the layout to an optimum, but even in such cases there will be instances that the mathematically optimum result might not be what you want.
It is said that George Bernard Shaw would examine galley proofs of his work and recast sentences, or even whole pages, in order to avoid unsightly word breaks, excessive white space caused by justification, and other typographical difficulties. Of course, he was published at a time when typesetters were sent to the block for committing the abominations above.
Unfortunately, there will always be an amount of manual intervention at the final edit of a book to correct these type of problems.
Please also have a look at Layout guidelines not exactly a multiple of \baselineskip