1

I used the geometry package with the option heightrounded and set parskip=0pt; I then got an underfull vbox message (badness 10000). But this disappeared after I set parskip=0pt plus .0001ex (.00001 did not work). Explanation?

  • TeX just needed a small amount of stretchy glue to play with: without it, it could not satisfy your desiderata; with it, it could. You gave it a small amount of discretion in terms of vertical spacing. (But you have to give it enough.) – cfr Sep 10 '15 at 1:22
6

You can get an underfull page notwithstanding the heightrounded setting (when \flushbottom is active) because of widow or club lines.

For instance

\documentclass{article}
\usepackage[textheight=4cm,heightrounded]{geometry}
\usepackage{kantlipsum}

%\clubpenalty10000
%\widowpenalty10000

\flushbottom

\begin{document}
\kant[1-10]
\end{document}

produces no underfull page, but as soon as I uncomment the two lines, so disallowing club and widow lines, I get three underfull pages.

If you look at the result with the commented lines, you can notice that the first page has a club line, because the second paragraph starts on page one with just a line. If \clubpenalty is set to 10000, this line is not accepted any more and, as a consequence, an underfull page results.

Setting a flexible \baselineskip is not a good workaround, in my opinion. Note that your chosen value of 0.00001pt is the same as 1sp. Now let me try

\documentclass{article}
\usepackage[textheight=4cm,heightrounded,showframe]{geometry}
\usepackage{kantlipsum}

\clubpenalty10000
%\widowpenalty10000

\flushbottom

\begin{document}
\kant[1-10]
\end{document}

where showframe is meant to draw a box around the text area, I still get

Underfull \vbox (badness 10000) has occurred while \output is active

for the first page, which is filled up nonetheless

enter image description here

Why is it so? First of all, recall that allowing even a minimal stretch component allows for arbitrary stretching. We have to cover 12pt for the “missing” line with the available stretch and we can distribute the stretch over eight interline spaces. The available stretch is 8sp and this means the stretch factor is

12 * 65536 / 8 = 98304

which of course will cause badness to be 10000, because it's 100 times the cube of the stretch factor, with a cut off at 10000 if exceeded.

In this case, to get a “perfect page” as far as badness is computed, you have to allow for 1.5pt of stretch (12/8 is needed). And indeed, setting

\baselineskip=1\baselineskip plus 1.5pt

gives no “underfull” warning.

A stretchable baseline skip can be good for “unattended typesetting”, where one doesn't look for high quality. I too use it sometimes, so not to be bothered by those messages when preparing the document; but high quality typesetting definitely doesn't benefit from this, unless we are typesetting some brochure or similar document.

Since you say to have 42 lines on your pages (and assuming 10pt font size), covering up a club line means distributing 12pt over 40 interline spaces; the badness is reported once it exceeds the value of \vbadness (default 1000), so when the stretch ratio exceeds 2.15 (the cube root of 10, because badness is the cube of the stretch ratio multiplied by 100). So, in order to have badness below 1000; now, if s is the wanted amount of stretch, we need 12pt/(40 s) = 2.15, so s = 0.645pt.

Do your own computation if your baseline skip is different.

There are better ways to cope with club or widow lines. Adjusting the length of a paragraph can be done with \looseness, for instance, or, better, by rewording.

Adding stretchability to \parskip is not the best, I believe, particularly if there are few paragraphs in a page, because all the stretch will be distributed only at paragraph beginnings.

  • But surely this is different from what I described in the comment above? Surely .00001pt glue constitutes only a trivial and indiscernible flexibility? – Toothrot Sep 10 '15 at 11:29
  • @Lawrence If you have to cover a club line, with a 40 line page and 12pt baseline skip, you need to distribute those 12pt over 38 interlines, that makes a need for 0.31579pt in each. Note that even 1sp flexibility allows for arbitrary stretching, but this will probably result in so high a badness that the Underfull \vbox message is issued nonetheless. – egreg Sep 10 '15 at 11:50
  • Nice point about the club/widow issue - it's another trap if \pagestretch etc are all 0, but as Lawrence points out it is probably not what threw the warnings he saw. I do agree (with egreg) about the \baselineskip kludge. It can be useful in some contexts, but for most documents it needs more careful thought. – Andrew Kepert Sep 10 '15 at 11:57
  • 1
    @AndrewKepert I expanded my answer also taking into account the proposed amount of flexibility. – egreg Sep 10 '15 at 12:08
  • 3
    @Lawrence Saying \hspace{0pt plus 3pt} doesn't mean that the space will be at most 3pt, if stretching it is needed. The stretch can be arbitrary, at the expense of badness. This happens for all types of glue, but not for shrinking, where the amount states an absolute maximum. That's by rule of TeX, blame Knuth for it. ;-) – egreg Sep 10 '15 at 12:20
2

This is to do with glue, one of the fundamental building blocks in TeX (which you don't see so much in LaTeX). In a nutshell, glue is the stuff that makes up skips (\parskip, \baselineskip, etc) and it can stretch or shrink to fill available space. Glue is used in horizontal or vertical skips (\hskip, \vskip). Each skip has its own amount of stretchiness and shrinkiness, specified by the plus and minus amounts. If it stretches or shrinks beyond the amount specified, it goes "bad", and the line & page breaking algorithms' jobs are to minimise badness.

Vertically, glue can be used between lines on a page to space them out (all lines separated by glue with similar stretchiness) so that pages are all the same height (the default) or make the spacing uniform with all spare space at the bottom by ending with a very (∞ly) stretchy blob of glue (a \raggedbottom option). Or any combination of such things.

So in the current context, TeX's page breaking algorithm is trying to make a page which should fit reasonably well, but is just fails due to small discrepancies, as all the glue on the page has no stretchiness. The default is that \baselineskip has no stretchiness and \parskip has a small amount, but you've needed to override the default \parskip, so the page ends up with no stretch or shrink. With a small amount of additional stretchiness between paragraphs, TeX will stop complaining that it can't fit the page to the stringent conditions asked of it. The output page will be almost identical.

A better solution might be to use \raggedbottom or to set the end-of-page glue to have a small stretchiness in some other way. Or you could set \baselineskip to have a tiny amount of stretchiness and shrinkiness, so that the additional space is imperceptibly added (or subtracted) between all lines. One of these will be needed if you subject your readers to long paragraphs.

  • I still wonder, though, when textheight is set to topskip + n*baselineksip, and there is nothing irregular on the page, whence those small discrepancies come. – Toothrot Sep 10 '15 at 8:31
  • My præferred solution is now to add .00001pt glue to the baselineskip. – Toothrot Sep 10 '15 at 9:20
  • 1
    @Lawrence re "I still wonder, ..." I would have guessed that it is accumulation of round-off errors. However, in fixed-precision arithmetic a+n*b and a+b+b+...+b should come to the same thing, so this seems unlikely. Maybe geometry is doing its calculations in a unit other than sp and the error is in the conversion to sp. You've shown that a few sp per page fixes it, so it looks like a rounding error. My advice: stop worrying about this and get back to worrying about whatever your document is about. (Unless the document you are writing is about precise layout control in TeX.) – Andrew Kepert Sep 10 '15 at 14:19
  • Further note: I just looked at geometry, and the calculation of page height to implement heightrounded (lines 700+ in the version I have) is all Plain TeX (not calc code) using \advance and \multiply. This should be accurate to the sp. – Andrew Kepert Sep 10 '15 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.