6

Consider the following MWE:

\documentclass{article}
\usepackage{lipsum}
\usepackage{booktabs}

\begin{document}

\lipsum[1]

\clearpage

\begin{table}[htbp]%
    \centering%
    \caption{Test table.}%
    \begin{tabular}{lcc}%
    \toprule
          a & b & c \\
    \bottomrule
    \end{tabular}%
\end{table}%

\end{document}

As seen in the output below, the table's heading is lower than the first line of text on the other page, which, IMHO, does not look good when using two-page mode for a document. Node that everything looks fine if the table is placed somewhere in the middle of the text.

Is this intended behavior for some reason I am missing? If not, how can I fix this?

Output

Edit: I just realized (thanks to Martin for giving me the idea) that this only happens when the caption is set above the table, not if it is below: moving the caption to the end of the table results in the baseline of the table's first line (a b c) being nearly (not quite, but close enough to look good considering the \toprule) on the same height as the opposing text's baseline.

2
  • I guess as you are using a float, a different set of rules applies. And I really don't think that it looks bad. As the table will always look somewhat different compared to the text. In a book you may not even notice the difference. Jul 16, 2013 at 11:59
  • @Martin: Now that you mention it, I did not notice the same with figures as opposed to tables (I'll edit my question accordingly), which makes the difference even worse from my point of view...
    – rainer
    Jul 16, 2013 at 12:03

3 Answers 3

6

There are two problems.

\abovecaptionskip, \belowcaptionskip

The standard classes always assume that the caption goes below the object. Thus the book class sets a space of 10pt above the caption and 0pt below the caption.

In your case the table captions go above the tables, thus the values of \abovecaptionskip and \belowcaptionskip should be exchanged. For example, package caption does this for you:

\documentclass{article}
\usepackage{lipsum}
\usepackage{booktabs}
\usepackage{caption}
\usepackage[pass,showframe]{geometry}

\begin{document}

\lipsum[1]

\clearpage

\begin{table}[htbp]%
    \centering%
    \caption{Test table.}%
    \begin{tabular}{lcc}%
    \toprule
          a & b & c \\
    \bottomrule
    \end{tabular}%
\end{table}%

\end{document}

\topskip

TeX/LaTeX tries to align the first lines of the pages. TeX knows a skip register \topskip. This space is decreased by the height of the first line or set to zero, if the result would be negative. Then the resulting glue is added at the top of the page. The LaTeX default for \topskip is the font size (10pt, 11pt, or 12pt).

In case of the top float we have a box with a large height, thus the inserted \topskip is zero. However, the first page contains a normal line with height 6.94444pt. \topskip is 10pt, thus 3.05556pt is inserted.

The following patch \topcaptionfix tries to compensate this:

  1. With the help of package zref-savepos the current vertical position is recorded in the .aux file as label. For a top placed float the .aux file writes the label:

    \zref@newlabel{zref@1}{\posy{43889459}}
    

    Thus the vertical position is 43889459sp. Thus the fix does not apply, if the vertical position of the float object is smaller/lower.

  2. The height of the first line needs to be estimated. The code assumes that the normal font is used for the caption containing letters not larger than uppercase letters (AZ). A different text can be specified by the optional argument. The default is Table. If different fonts/sizes are used for the caption, then they need to be specified ne line \settoheight.

  3. Package caption also adds \struts. They are invisible objects occupying the vertical space of \baselineskip. Sometimes it helps for the alignment of caption lines. This feature can be configured by option strut, e.g. it can be turned off by \captionsetup{strut=off}.

  4. Finally the estimated height of the first line, the height of the \strut, if set and the value of \topskip are compared to calculate the space that needs to be inserted to correct the position of the float caption.

Example file:

% \showboxbreadth=\maxdimen
% \showboxdepth=\maxdimen

\documentclass{article}
\usepackage{lipsum}
\usepackage{booktabs}
\usepackage{caption}
\usepackage{zref-savepos}
\usepackage[pass,showframe]{geometry}

\makeatletter
\zref@require@unique
\providecommand*{\zref@unique@next}{%
  \stepcounter{zref@unique}%
}
\providecommand*{\zsaveposy}{\zsavepos}
\newcommand*{\topcaptionfix}[1][Table]{%
  \zref@unique@next
  \zsaveposy{\thezref@unique}%
  \zifrefundefined{\thezref@unique}{%
  }{%
    \ifdim\zposy{\thezref@unique}sp<43889459sp %
    \else
      \begingroup
        % estimated height of the first line of the caption
        \settoheight{\dimen@}{#1}%
        \caption@ifstrut{%
          \ifdim\dimen@>\ht\strutbox
            \ifdim\topskip>\dimen@
              \vskip\dimexpr\topskip-\dimen@\relax
            \fi
          \else
            \ifdim\topskip>\dimen@
              \vskip\dimexpr\topskip-\ht\strutbox\relax
            \fi
          \fi
        }{%
          \ifdim\topskip>\dimen@
            \vskip\dimexpr\topskip-\dimen@\relax
          \fi
        }%
      \endgroup
    \fi
  }%
}
\makeatother

\begin{document}

\lipsum[1]

% \showlists

\clearpage

\begin{table}[htbp]%
    \centering
    \topcaptionfix
    \caption{Test table.}%
    \begin{tabular}{lcc}% 
    \toprule
          a & b & c \\
    \bottomrule
    \end{tabular}%
\end{table}%

% \showlists

\end{document}

For those, who are familiar with TeX's box representations, can enable the commented lines \showbox... and \showlists. Then TeX prints the current vertical list into the .log file. For example, the start of the second page (variant with strut):

### current page:
\write-{}
\glue(\topskip) 0.0
\vbox(41.72083+0.0)x345.0
.\pdfsavepos
.\write1{\zref@newlabel{zref@1}{\posy{\Z@C@posy }}}
.\glue 1.60004
.\write1{\@writefile{lot}{\protect \contentsline {table}{\protect \numberline \ ETC.}
.\glue 0.0
.\glue(\parskip) 0.0
.\hbox(8.39996+3.60004)x345.0

The glue with value 1.60004pt is inserted to correct the position of the table caption.

Package geometry provides option showframe, that allows a visual control of the result:

Page 1:

page 1

Page 2:

page 2

1
  • Thanks, the caption package put me on the right track: it works for the article class, but does not in scrreprt, which I am using outside of my MWE. However, captions=tableheading does the trick there.
    – rainer
    Jul 17, 2013 at 7:26
2

Well it's a sort of feature...

The float box is set before it knows whether it will be placed at top of page and the float placement doesn't know what is inside the box when it places it at the top of the page.

It is possible to make the setting depend on position, but it goes deep into latex internal code in the output routine so probably it's incompatible with something. See

Formatting floats differently based on placement

1

One way to do this is to use float package to restyle the table environment. e.g. the code:

\documentclass{article}
\usepackage{lipsum}
\usepackage{booktabs}
\usepackage{float}

\floatstyle{plaintop}
\restylefloat{table}

\begin{document}

\lipsum[1]

\clearpage

\begin{table}[htbp]%
\centering%
\caption{Test table.}%
\begin{tabular}{lcc}%
\toprule
      a & b & c \\
\bottomrule
\end{tabular}%
\end{table}%
\end{document}

will give: enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .