[Tex/LaTex] Understanding line height / line spacing / baselineskip in LaTeX

fontsizeline-spacing

I tried for a while now to figure out how LaTeX is determining the spacing between two lines but instead of getting clearer I'm more and more confused (and it seems the Internet is mostly confused, too), so let's see if turning it into a question can clarify it!

The naive assumption

First of all my naive understanding of "line height" or what I assumed was the value stored in \baselineskip was the following

Consequently I assumed setting \baselineskip equal to font size should result in lines "touching" each other – no actual empty space between lines (including full ascenders and descenders of the font).

Reality seems to differ

However it became clear to me, that this can't be true. Consider the following:

\documentclass{article}

\begin{document}
\setlength{\parindent}{0pt}

% font size = \baselineskip - should result in lines "touching", shouldn't it?
\fontsize{10pt}{10pt}\selectfont
\textbar The quick brown fox jumps over the lazy dog\\
\textbar The quick brown fox jumps over the lazy dog

\fontsize{20pt}{20pt}\selectfont
\textbar The quick brown fox...\\
\textbar The quick brown fox...

\fontsize{30pt}{30pt}\selectfont
\textbar The quick brown fox...\\
\textbar The quick brown fox...

\end{document}

While my assumption seems to hold for smaller font sizes, the larger the font size the more obvious it becomes this can't be the whole truth!

Set line height in multiples of font size?

Similar confusion is also apparent for people trying to set the line spacing to a specific multiple of the font size.

Using \renewcommand*\baselinestretch{1.5}\selectfont or similar does many things – but not result in what one expects to be a one-and-a-half line spacing!

This even resulted in the creation of the setspace package, which is often recommended to achieve the desired result. Looking at the source reveals however, that the authors were not fully able to understand what LaTeX was doing either:

% GT:  Sat 28 Sep 1996:  No, I don't know understand the line spacing
% algorithms!  If someone (LaTeX team) can enlighten me as to the
% general rule, please do!  It would be very pleasant if setspace.sty
% were suited for document font sizes other than 10, 11 and 12 pt.

And in fact the package specifies some hardcoded values for the three font sizes mentioned to achieve consistent line spacing at least for the most commonly used font sizes.

Why care?

Obvious question: Why care so much if whatever TeX does seems to "look good" at least.

In my specific case I want to implement something in TeX that works like the line-height property in CSS/SVG, so I can set the line spacing precisely in multiples of the font size.
So far a solution is elusive to me which kind off bugs me because I always thought this was the stuff TeX was supposed to be superior in, but it turns out in this particular case it's reluctant to comply.

Therfore I hope you can give me the clarity I need to implement what I want and explain what spacings control the actual distance of two font baselines in LaTeX and how \baselineskip plays into this.

Best Answer

Your first assumption and picture of \baselineskip were correct, but

Consequently I assumed setting \baselineskip equal to font size should result in lines "touching" each other

Is wrong for two separate reasons.

Firstly the "font size" is an essentially arbitrary number assigned by the font designer \fontsize{10pt}{10pt}\selectfont selects a font with nominal size 10pt and \baselineskip equal to 10pt but the actual height of the letters (especially parentheses and accented captitals, or even unaccented capitals) may be more than 10pt. So this may or may not result in \baselineskip glue being added depending if the height of the letters actually used on the line is more or less than 10pt.

Secondly teX does not force the baselineskip by using no space (or negative space) two over-height lines do not over-print, being set to a forced \baselineskip spacing. If the space to be added would be less than the parameter \lineskiplimit then a length \lineskip is used instead.

By default in the standard classes \lineskip is 1pt so you will see a minimum 1pt separation if the baselines would touch but (slightly strangely) \lineskiplimit is 0pt so the distance can approach zero without \lineskip being used, which will cause a "jump" in interline space if the height of the content is gradually increased.

If you add

\showoutput
\showboxdepth=3

to your test file, note first that it says

LaTeX Font Warning: Size substitutions with differences
(Font)              up to 5.12pt have occurred.

So the fonts used were not always the size requested (but \baselineskip was always exactly as requested) this explains why the effects are more apparent at some sizes. The log will show

\vbox(633.0+0.0)x407.0
.\glue 16.0
.\vbox(617.0+0.0)x345.0, shifted 62.0
..\vbox(12.0+0.0)x345.0, glue set 12.0fil
...\glue 0.0 plus 1.0fil
...\hbox(0.0+0.0)x345.0
..\glue 25.0
..\glue(\lineskip) 0.0
..\vbox(550.0+0.0)x345.0, glue set 426.9944fil
...\write-{}
...\glue(\topskip) 2.5
...\hbox(7.5+2.5)x345.0, glue set 143.77742fil []
...\penalty 300
...\glue(\baselineskip) 0.0
...\hbox(7.5+2.5)x345.0, glue set 143.77742fil []
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 1.945
...\hbox(15.555+5.185)x345.0, glue set 152.1931fil []
...\penalty 300


...\glue(\lineskip) 1.0


...\hbox(15.555+5.185)x345.0, glue set 152.1931fil []
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 6.155
...\hbox(18.66+6.22)x345.0, glue set 113.70607fil []
...\penalty 300
...\glue(\baselineskip) 5.12
...\hbox(18.66+6.22)x345.0, glue set 113.70607fil []
...\glue -5.0
...\glue 0.0 plus 1.0fil
...\glue 0.0
...\glue 0.0 plus 0.0001fil
..\glue(\baselineskip) 23.55556
..\hbox(6.44444+0.0)x345.0, glue set 170.0fil
...\glue 0.0 plus 1.0fil
...\OT1/cmr/m/n/10 1
...\glue 0.0 plus 1.0fil

If you allow the fonts at any size by adding \RequirePackage{fix-cm} as the first line you get no font size warning

enter image description here

and a log of

\vbox(633.0+0.0)x407.0
.\glue 16.0
.\vbox(617.0+0.0)x345.0, shifted 62.0
..\vbox(12.0+0.0)x345.0, glue set 12.0fil
...\glue 0.0 plus 1.0fil
...\hbox(0.0+0.0)x345.0
..\glue 25.0
..\glue(\lineskip) 0.0
..\vbox(550.0+0.0)x345.0, glue set 427.45435fil
...\write-{}
...\glue(\topskip) 2.5
...\hbox(7.5+2.5)x345.0, glue set 143.77742fil []
...\penalty 300
...\glue(\baselineskip) 0.0
...\hbox(7.5+2.5)x345.0, glue set 143.77742fil []
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 2.5
...\hbox(15.0+5.0)x345.0, glue set 159.07242fil []
...\penalty 300
...\glue(\baselineskip) 0.0
...\hbox(15.0+5.0)x345.0, glue set 159.07242fil []
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 2.5
...\hbox(22.5+7.5)x345.0, glue set 66.10855fil []
...\penalty 300
...\glue(\baselineskip) 0.0
...\hbox(22.5+7.5)x345.0, glue set 66.10855fil []
...\glue -5.0
...\glue 0.0 plus 1.0fil
...\glue 0.0
...\glue 0.0 plus 0.0001fil
..\glue(\baselineskip) 23.55556
..\hbox(6.44444+0.0)x345.0, glue set 170.0fil
...\glue 0.0 plus 1.0fil
...\OT1/cmr/m/n/10 1
...\glue 0.0 plus 1.0fil