2

I have a tabular environment with three columns aligned as {rcl} such that text in the middle column is centered internally within the column. I want the whole table to be positioned in the page such that the center column is centered horizontally along the page. The left and right columns have a variable length that can generally be assumed to be different from one another and from the length of the center column, so centering the whole table will not generally center it with reference to the middle column, but rather with regards to the midpoint (horizontally) of the length of all of its columns.

Here is a MWE where I used fboxes to show where the table columns are. Essentially I want the center/middle box to be positioned in the global center on the frame/page.

\documentclass{beamer}
\usetheme{default}
\begin{document}
\begin{frame}
\begin{center}
\fbox{
\begin{tabular}{rcl}
\fbox{one} & \fbox{two} & \fbox{three four five} \\
\end{tabular}
}
\end{center}
\end{frame}
\end{document}
3

You can do calculations of page positions:

\documentclass{beamer}
\usepackage{tikz}
\usetheme{default}
\usepackage{zref-savepos}

\begin{document}
\begin{frame}
\tikz[overlay,remember picture]\draw[red] (current page.north)--(current page.south);

\centering
\hspace*{\dimexpr\zposx{end}sp-\zposx{midright}sp-\zposx{midleft}sp+\zposx{start}sp}%
\begin{tabular}{@{}rcl@{}}
\zsavepos{start}\fbox{one}\zsavepos{midleft}&%
\tikz{\draw(0,0)--(1,0);\draw(0.5,0)--++(0,0.5);}& 
\zsavepos{midright}\fbox{three four five}\zsavepos{end}\\
\end{tabular}

\end{frame}
\end{document}

enter image description here

1

This solution uses \settowidth. I added a \rule at the center for comparison.

\documentclass{beamer}
\usetheme{default}
\newlength{\tempdima}
\newlength{\tempdimb}

\begin{document}
\begin{frame}
\begin{center}
\settowidth{\tempdima}{\fbox{one}}%
\settowidth{\tempdimb}{\fbox{three four five}}%
\rule{1pt}{\baselineskip}\\
\hspace{\dimexpr \tempdimb-\tempdima}\fbox{
\begin{tabular}{rcl}
\fbox{one}  & \fbox{two} & \fbox{three four five} \\
\end{tabular}
}
\end{center}
\end{frame}
\end{document}

This solution uses \savebox instead. It is slightly more efficient.

\documentclass{beamer}
\usetheme{default}
\newsavebox{\tempboxa}
\newsavebox{\tempboxb}

\begin{document}
\begin{frame}
\begin{center}
\savebox{\tempboxa}{\fbox{one}}%
\savebox{\tempboxb}{\fbox{three four five}}%
\rule{1pt}{\baselineskip}\\
\hspace{\dimexpr \wd\tempboxb-\wd\tempboxa}\fbox{
\begin{tabular}{rcl}
\usebox{\tempboxa}  & \fbox{two} & \usebox{\tempboxb} \\
\end{tabular}
}
\end{center}
\end{frame}
\end{document}
  • This is nice but does not scale easily to multiple rows, since it seems that you would have to manually copy parts of each row to the preparation portion of the script (savebox/settowidth)… – Daniel Naftalovich May 2 '16 at 2:56
  • OTOH, if you know the widest element in each column then the solution is relatively easy. – John Kormylo May 2 '16 at 12:27
1

Well, is is perhaps worth noting that, if the alignment of the columns is really what the OP says (rcl without vertical rules, at least to the left of the first column and to the right of the last one), there is also a trivial solution: just pretend that the two outer columns have zero width.

% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly 
                                 % declare the paper format.

\usepackage[T1]{fontenc}         % Not always necessary, but recommended.

\usepackage[ascii]{inputenc}     % Just to check that the source is still pure,
                                 % 7-bit-clean ASCII when you execute it, as it
                                 % was when I wrote it.
% End of standard header.  What follows pertains to the problem at hand.

\usepackage{array}

\makeatletter

% Hand crafted versions of "\llap" and "\rlap".  Note that it is irrelevant 
% which column specifier (l, c, or r) is used here; so, we just use the one 
% that reminds what the column alignment looks like.
\newcolumntype{A}{>{\hb@xt@\z@\bgroup\hss}r<{\egroup}}
\newcolumntype{B}{>{\hb@xt@\z@\bgroup}l<{\hss\egroup}}

\makeatother



\begin{document}

Text before.

\begin{center}
    % The picture is here simply to draw the line the marks the central axis.
    \setlength{\unitlength}{1cm}
    \begin{picture}(0,0)
        \linethickness{.2pt}
        \put(0,1){\line(0,-1){10}}
    \end{picture}\\[-\baselineskip]
    %
    % Here is the tabular:
    \begin{tabular}{A|c|B}
        % Vertical bars are inserted around the middle column, in order to 
        % clearly show its boundaries, but you can remove them.
        Left & Center & Right  \\
        Short & Somewhat longer & Narrow  \\
        This is a pretty long entry & This is not as much &  \\
         & Random text & Hi!  \\
        Lorem ipsum & Dolor sit & Amet  \\
        Consectetur & Adipisci elit & Mus  \\
        Another pretty long entry & Shorter one & Fringilla  \\
        (Boring, isn't it?) & Iam ligula & Abc  \\
        A & B & C  \\
        This makes ten lines: & it should be\ldots & \ldots enough!  \\
    \end{tabular}
\end{center}

Text after.

\end{document}

Here is what the output looks like:

Output of the above code

Addendum: Here is a brief explanation of the code, as requested by Daniel’s comment.

The A column specifier is defined in such a way to virtually wrap the cell contents in a \llap command; indeed, it prepends (the equivalent of) \hbox to 0pt {\hss to the cell contents, and appends (the equivalent of) } after them. This has the effect of making the contents behave as a box of null width (\hbox to 0pt), with the text sticking out to the left (because \hss is to the left of the text itself).

The same holds true for the B specifier, but with left and right interchanged. So, this specifier virtually wraps the cell contents in a \rlap command, since (the equivalent of) \hbox to 0pt { is put before the, and \hss} after them; having, this time, the \hss command on the right, the text will protrude towards that direction.

See also The TeXbook, p. 82.

  • Can you please explain the code for the commands? – Daniel Naftalovich May 4 '16 at 0:52
  • @DanielNaftalovich: please see edit. – GuM May 6 '16 at 21:32
  • Easier and safer: \usepackage{array,collcell} \newcommand{\zeroright}[1]{\makebox[0pt][r]{#1}} \newcommand{\zeroleft}[1]{\makebox[0pt][l]{#1}} \newcolumntype{A}{>{\collectcell\zeroright}c<{\endcollectcell}} \newcolumntype{B}{>{\collectcell\zeroleft}c<{\endcollectcell}} – egreg May 6 '16 at 21:48
  • @egreg: I believe that, in a simple case like this, using such a powerful tool as the collcell package is unnecessarily complicated (and cumbersome). After all, this was meant to be a quick fix, tailored for a specific situation. Of course, you are free to disagree… (and knowing you, you will! ;-) – GuM May 7 '16 at 22:54
  • @GustavoMezzetti I always prefer a higher level solution. – egreg May 7 '16 at 22:56

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.