Vertical Spacing within align environment accounting for fractions

The default vertical spacing within an align environment seems very tight when there are fractions in the lines.

I am aware of three manual tweaks that can be applied:

1. Adjust the value \jot.
2. Add a vertical space on each line where necessary via \\[<amount>].
3. Use the spreadlines environment from the mathtools package.

Solutions 1 and 3 add vertical space even between the lines that don't need them, so if the set of equations has lines without fractions (and lines with fractions), the spacing is not quite right.

Question:

Is there not some automated solution to always leave the appropriate vertical space between the bottom of one line and the top of the next?

Code:

\documentclass{article}
\usepackage{mathtools}% includes amsmath

\begin{document}
\begin{minipage}[t]{0.20\linewidth}
\textbf{Nice}
\begin{align*}
x &= 73 \times 2\\
&= 146
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.25\linewidth}
\textbf{Not so nice}
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%

\bigskip\par\noindent
\textbf{Manual Tweak Options:}
\medskip\par\noindent
\begin{minipage}[t]{0.25\linewidth}
\textbf{Tweak jot}
\setlength{\jot}{8pt}% tweak
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.30\linewidth}
\begin{align*}
x &= \frac{146}{10}\\[5pt]% tweak
&= \frac{73}{5}
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.30\linewidth}
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%
\end{document}


Testing Proposed fix:

I tested the proposed fix, and it does seem to fix the "Not so nice" section:

Not sure I like the additional vertical space at the top.

But furthermore, it also adds spacing where it is not needed as was the case in the section that was previously "Nice":

In cases where there are manual adjustments, they should probably not be extended (or only extended if the spacing is not sufficient. Personally I can work without this, but perhaps a method of disabling it would be good:

Code:

\documentclass{article}
\usepackage{mathtools}% includes amsmath

\begin{document}
\par\noindent
%---------------------------------------- Oringally "Nice"
\begin{minipage}[t]{0.30\linewidth}
\textbf{Nice}
\begin{align*}
x &= 73 \times 2\\
&= 146
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.30\linewidth}
\makeatletter
\def\align@preamble{%
&\hfil
\setboxz@h{\@lign$\m@th\displaystyle{##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\tabskip\z@skip
&\setboxz@h{\@lign$\m@th\displaystyle{{}##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\hfil
\tabskip\alignsep@
}%
\makeatother
%
%
\textbf{With 2012-05-09 fix:}
\begin{align*}
x &= 73 \times 2\\
&= 146
\end{align*}
\end{minipage}%

\bigskip\par\noindent
%---------------------------------------- Oringally "Not so Nice"
\begin{minipage}[t]{0.30\linewidth}
\textbf{Not so nice}
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.30\linewidth}
\makeatletter
\def\align@preamble{%
&\hfil
\setboxz@h{\@lign$\m@th\displaystyle{##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\tabskip\z@skip
&\setboxz@h{\@lign$\m@th\displaystyle{{}##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\hfil
\tabskip\alignsep@
}%
\makeatother
%
\textbf{With 2012-05-09 fix:}
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%

\bigskip\par\noindent
\textbf{Manual Tweak Options:}
\medskip\par\noindent
\begin{minipage}[t]{0.30\linewidth}
\textbf{Tweak jot}
\setlength{\jot}{8pt}% tweak
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.30\linewidth}
\makeatletter
\def\align@preamble{%
&\hfil
\setboxz@h{\@lign$\m@th\displaystyle{##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\tabskip\z@skip
&\setboxz@h{\@lign$\m@th\displaystyle{{}##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\hfil
\tabskip\alignsep@
}%
\makeatother
%
\textbf{With 2012-05-09 fix:}
\setlength{\jot}{8pt}% tweak
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%
%

\bigskip\par\noindent
\begin{minipage}[t]{0.30\linewidth}
\begin{align*}
x &= \frac{146}{10}\\[5pt]% tweak
&= \frac{73}{5}
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.30\linewidth}
\makeatletter
\def\align@preamble{%
&\hfil
\setboxz@h{\@lign$\m@th\displaystyle{##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\tabskip\z@skip
&\setboxz@h{\@lign$\m@th\displaystyle{{}##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\hfil
\tabskip\alignsep@
}%
\makeatother
%
\textbf{With 2012-05-09 fix:}
\begin{align*}
x &= \frac{146}{10}\\[5pt]% tweak
&= \frac{73}{5}
\end{align*}
\end{minipage}%

\bigskip\par\noindent
\begin{minipage}[t]{0.30\linewidth}
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.30\linewidth}
\makeatletter
\def\align@preamble{%
&\hfil
\setboxz@h{\@lign$\m@th\displaystyle{##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\tabskip\z@skip
&\setboxz@h{\@lign$\m@th\displaystyle{{}##}$}%
\ifdim\ht\z@<\ht\strutbox@
\ht\z@\ht\strutbox@
\dimen@\ht\strutbox@
\ht\strutbox@\dimen@
\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\hfil
\tabskip\alignsep@
}%
\makeatother
%
\textbf{With 2012-05-09 fix:}
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%
\end{document}

-
I'm afraid there isn't such an automatic method. However, I think that in a align the distance between the lines (the equals signs, to give an indication) should generally be constant. Fine tuning math alignments can be done only looking at them and knowing the meaning of the formulas. – egreg May 6 '12 at 8:36
@egreg: I agree with the fine tuning part, but it seems that if there was just some minimum setting for the space between the depth of one line and the height of another that would go a long way. – Peter Grill May 7 '12 at 0:12
I'm trying to add a small vertical space between two lines of maths, but your commands don't work when I just type, for example, $\setlength{\jot}{8pt}$. I am just trying to do this for the posts that I put on SE - as with math.stackexchange.com/questions/988865/…. – ahorn Oct 24 '14 at 9:43
@ahorn: I don't think the math.SE site supports full TeX. I'd suggest compose a fully compilable MWE including \documentclass and the appropriate packages that reproduces the problem and post a new question on TeX.SE. – Peter Grill Oct 24 '14 at 17:31
May I observe the cellspace package does a similar job for tabular/arrays. It defines a minimal vertical spacing at the top and bottom of cells in a column. – Bernard Aug 6 '15 at 14:47

AMS alignments box and measure each cell anyway so you can check if the cell height is larger than a strut you can locally increase the strut height.

Code updated to use > instead of < so it opens up big entries not small ones:-) Also does not do anything on first row to avoid adding space above the display.

\documentclass{article}
\usepackage{mathtools}% includes amsmath

\makeatletter

\newlength\minalignvsep

\def\align@preamble{%
&\hfil
\setboxz@h{\@lign$\m@th\displaystyle{##}$}%
\ifnum\row@>\@ne
\ifdim\ht\z@>\ht\strutbox@
\dimen@\ht\z@
\ht\strutbox\dimen@
\fi\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\tabskip\z@skip
&\setboxz@h{\@lign$\m@th\displaystyle{{}##}$}%
\ifnum\row@>\@ne
\ifdim\ht\z@>\ht\strutbox@
\dimen@\ht\z@
\ht\strutbox@\dimen@
\fi\fi
\strut@
\ifmeasuring@\savefieldlength@\fi
\set@field
\hfil
\tabskip\alignsep@
}
\makeatother

\minalignvsep.15em

\begin{document}

\begin{minipage}[t]{0.20\linewidth}
\textbf{Nice}
\begin{align*}
x &= 73 \times 2\\
&= 146
\end{align*}
\end{minipage}%

%
\begin{minipage}[t]{0.25\linewidth}
\textbf{Not so nice}
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%

\bigskip\par\noindent
\textbf{Manual Tweak Options:}
\medskip\par\noindent
\begin{minipage}[t]{0.25\linewidth}
\textbf{Tweak jot}
\setlength{\jot}{8pt}% tweak
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.30\linewidth}
\begin{align*}
x &= \frac{146}{10}\\[5pt]% tweak
&= \frac{73}{5}
\end{align*}
\end{minipage}%
%
\begin{minipage}[t]{0.30\linewidth}
\begin{align*}
x &= \frac{146}{10}\\
&= \frac{73}{5}
\end{align*}
\end{minipage}%
\end{document}

-
This works for the case where there was a faction, but unfortunately also increases the spacing in the case where it is not needed. Have provided an updated MWE that test this. – Peter Grill May 10 '12 at 0:35
Also, not sure why, but I had to repeat the code in the MWE. Ran into problems if I tried to define a macro to apply the patch within a group. – Peter Grill May 10 '12 at 0:35
Code updated, hopefully works better now. – David Carlisle May 10 '12 at 9:59
Yes, this definitely works much better. How do I define a command to apply this patch? I attempted to define \newcommand{\AlterAlignPreamble}{\def\align@preamble{...}} within the \makeatletter, but this results in Illegal parameter number in definition of \align@preamble., which I assume has something to do with the ## (which I have not encountered before). – Peter Grill May 10 '12 at 17:41
it's only ## because it's in a def, so if you want to put it in another one it would be #### but simpler and more efficient than re-doing the whole definition everytime would be to just define it once in a package file but with a different name \def\davids@preamble{....} then you just need to define \def\switchpreamble{\let\align@preamble\davids@preamble} – David Carlisle May 10 '12 at 17:53

A much simpler method:

Instead of using \\ for ending a line, use \\[0.5ex]. The optional argument in the brackets requests additional whitespace. The unit ex corresponds to the height of the character "x" in the current font.

-
Adding vertical spacing via the optional parameter to \\  was already mentioned in the question as manual option #2 and in the "Add vertical space" example. Looking for an automated method so that I don't need to tweak every case. – Peter Grill May 5 at 21:51