Vertical align table column to center until it grows too high?

MWE:

\documentclass{article}

\usepackage{lipsum}

\begin{document}

\newcommand{\mytable}[1]{
\begin{tabular}{ | l | p{0.75\linewidth} | }
\hline
\Huge X & #1 \\
\hline
\end{tabular}
}

\mytable{Single line should be centered on the X}

\bigskip

\mytable{Whole paragraph should be flush at top with the X.  \lipsum[1]}

\end{document}


This currently produces:

The first example shows some "shorter" content, in terms of height, and the second example shows taller content. When the height of the content in the second column is less than the height of the X, I want the second column's content to be vertically centered on the X. When the height of the content in the second column is greater than the height of the X, I want the top of the second column's content to be flush with the top of the X. How can I achieve this? Thanks!

EDIT:

This is pretty close to what I want:

\documentclass{article}

\usepackage{lipsum,calc}

\begin{document}

\newcommand{\mytable}[1]{
\begin{tabular}{ | l | l | }
\hline
\raisebox{-\height}{\Huge X}
&
\begin{minipage}[t][\maxof{\height}{\totalheightof{\Huge X}}][c]{10cm}
#1
\end{minipage}
\\
\hline
\end{tabular}
}

\mytable{Single line should be centered on the X}

\bigskip

\mytable{Whole paragraph should be flush at top with the X.  \lipsum[1]}

\end{document}


But why does the minipage seem to add vertical space above it when [c] is used to vertically center the internal content?

• I've updated my answer, maybe this solution fits your needs. – Skillmon Sep 3 '17 at 13:13
• Thanks for the answers! I couldn't let this rest, ended up coming with my own solution, which I've added. I'm hanging out a bit to see if anyone has any feedback on which answer is best and why, or at least to see if any clearly garner more points than the others. – dsedivec Sep 3 '17 at 17:27
• I'm going to select my answer as my preferred answer if only because it's simpler, but I'll be listening for feedback from others who are more experienced, such as for conditions under which my solution breaks but @Skillmon's, which is my second choice, works properly. Thanks again everyone! – dsedivec Sep 5 '17 at 22:57

I don't see how to make it automatic. Instead, I propose two different commands, to be used in each specific case:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{lipsum,calc}
\usepackage{makecell, cellspace}
\setlength\cellspacetoplimit{5pt}
\setlength\cellspacebottomlimit{4pt}

\newcommand{\myowntable}[1]{
\begin{tabular}{ |Sl | p{10cm} | }
\hline
\makecell{\Huge X}
& #1%
\\
\hline
\end{tabular}
}

\newcommand{\mylongowntable}[1]{
\begin{tabular}{ |Sl | p{10cm} | }
\hline
\raisebox{-0.6\height}{\Huge X}
& #1%
\\
\hline
\end{tabular}
}

\begin{document}

\myowntable{Single line should be centered on the X}
\bigskip

\mylongowntable{Whole paragraph should be flush at top with the X. \lipsum[1]\leavevmode\vspace*{-2ex}}

\end{document}


New answer: (with better code -- I think)

It should detect whether the height and depth of the right column is bigger than the height and depth of the X in a reliable way and according to that sets the table in two distinct ways which don't require guessing of any lengths for a \raisebox (thanks to @Bernard for his great solution on the table for a small right column):

\documentclass[preview,border=4mm]{standalone}

\usepackage{array}
\usepackage{lipsum,calc}
\usepackage{makecell, cellspace}
\setlength\cellspacetoplimit{5pt}
\setlength\cellspacebottomlimit{3pt}

\newdimen\Xtotal
\newdimen\Xwidth
\newdimen\partotal

\newcommand{\mytable}[2][10cm]{
\setbox0\hbox{\Huge X}%
\Xtotal=\dimexpr\ht0+\dp0\relax%
\Xwidth=\wd0\relax%
\setbox0\hbox{\parbox[t]{#1}{#2}}%
\partotal=\dimexpr\ht0+\dp0\relax%
\ifdim\partotal>\Xtotal\relax%
\begin{tabular}{ | Sl | p{#1} | }%
\hline
\parbox[b][\ht0][t]{\Xwidth}{\Huge X}%
& #2\\
\hline
\end{tabular}
\else%
\begin{tabular}{ | Sl | p{#1} | }
\hline
\makecell{\Huge X}
& #2%
\\
\hline
\end{tabular}
\fi%
}

\begin{document}

\mytable{Single line should be centered on the X}

\bigskip

\mytable{Whole paragraph should be flush at top with the X.  \lipsum[1]}

\bigskip

\mytable{Two lines just to check how it looks on this lovely X. So here they
come}

\end{document}


The following does what you want (but is no pretty code -- don't accept my answer before waiting a good time to see if someone has a better answer):

\documentclass[preview,border=4mm]{standalone}

\usepackage{array}
\usepackage{lipsum,calc}
\usepackage{makecell, cellspace}
\setlength\cellspacetoplimit{5pt}
\setlength\cellspacebottomlimit{4pt}

\newdimen\hugewidth

\begin{document}

\newcommand{\mytable}[2][10cm]{
\setbox0\hbox{\Huge X}%
\hugewidth=\wd0\relax%
\setbox0\hbox{#2}%
\ifdim\wd0>#1\relax% paragraph is too wide for one row
\setbox0\hbox{\parbox[t]{#1}{#2}}%
\begin{tabular}{ | Sl | p{#1} | }%
\hline
\parbox[b][\ht0][t]{\hugewidth}{\Huge X}%
& #2\\
\hline
\end{tabular}
\else%
\begin{tabular}{ | Sl | p{#1} | }
\hline
\makecell{\Huge X}
& #2%
\\
\hline
\end{tabular}
\fi%
}

\mytable{Single line should be centered on the X}

\bigskip

\mytable{Whole paragraph should be flush at top with the X.  \lipsum[1]}

\bigskip

\mytable{Two lines just to check how it looks on this lovely X. So here they
come}

\end{document}

\documentclass{article}

\usepackage{array}
\usepackage{lipsum,calc}

\newdimen\hugeheight
\newdimen\hugewidth

\begin{document}

\newcommand{\mytable}[1]{
\setbox0\hbox{\Huge X}%
\hugeheight=\ht0\relax%
\hugewidth=\wd0\relax%
\setbox0\hbox{\parbox[b]{10cm}{#1}}%
\ifdim\ht0>\hugeheight\relax%
\begin{tabular}{ | l | p{10cm} | }
\hline
\smash{\raisebox{-0.6\hugeheight}{\Huge X}} & #1\\
\hline
\end{tabular}%
\else%
\begin{tabular}{ | m{\hugewidth} | p{10cm} | }
\hline
\Huge X
&
#1
\\
\hline
\end{tabular}%
\fi%
}

\mytable{Single line should be centered on the X}

\bigskip

\mytable{Whole paragraph should be flush at top with the X.  \lipsum[1]}

\bigskip

\mytable{Two lines just to check how it looks on this lovely X. So here they
come}

\end{document}


• Nice! I didn't think of conditionally changing the tabular layout based on the height of the boxes, that's actually really simple. – dsedivec Sep 3 '17 at 17:00

It's a shame there seems to be no solution without using raisebox with some random number. By adjusting \fboxsep in the code below one has control over the spacing inside a cell:

\documentclass{article}
\usepackage{lipsum,calc}

\renewcommand{\fboxsep}{4pt} %adjust this to alter the spacing inside the table
\newcommand{\mytable}[1]{
\noindent\begin{tabular}{ | @{}c @{}|@{} c @{}|@{} c @{}| }
\hline
\raisebox{1.8ex}{\fbox{\begin{minipage}[t][][c]{\widthof{\Huge X}}\Huge X \end{minipage}}} &
\raisebox{1.8ex}{\fbox{\begin{minipage}[t][\maxof{\height+0.1ex}{\heightof{\Huge X}}][c]{10cm}
#1
\end{minipage}}}
\\
\hline
\end{tabular}
}

\begin{document}

\mytable{Single line should be centered on the X}

\bigskip

\mytable{Whole paragraph should be flush at top with the X.  \lipsum[1]}

\bigskip

\mytable{Now with two lines, just for fun. The lines should not be centered, since there vertical space exceeds the X.}

\bigskip

\mytable{lets \\ make \\ it \\ four}

\end{document}


For reasons I do not understand, \begin{minipage}[t][][c]... puts itself entirely below the baseline—zero height, all depth. Below solution gets the top of the two columns' boxes at the same place, I believe. I am not sure if \normalbaselineskip was the correct target for me to raise both boxes up to, but FWIW it looks right. (I also added cellspace after seeing Bernard and Skillmon use it, since it does make the result more visually pleasing, but it is not strictly necessary.)

\documentclass{article}

\usepackage{lipsum,calc,etoolbox,cellspace}

\newtoggle{drawframes}
% Uncomment to see frames.
% \toggletrue{drawframes}
\newcommand{\maybefbox}[1]{\iftoggle{drawframes}{\fboxsep=0pt\fbox{#1}}{#1}}

\begin{document}

\newcommand{\mytable}[1]{
\begin{tabular}{ | Sl | Sl | }
\hline
\maybefbox{\raisebox{-\height + \normalbaselineskip}{\Huge X}}
& \maybefbox{\raisebox{\normalbaselineskip}{%
\begin{minipage}
[t]
[\maxof{\totalheight}{\totalheightof{\Huge X}}]
[c]
{0.75\linewidth}
#1
\end{minipage}}}
\\
\hline
\end{tabular}
}

\mytable{Single line should be centered on the X}

\bigskip

\mytable{Whole paragraph should be flush at top with the X.  \lipsum[1]}

\end{document}