# Coloured underlines of equations and text in LaTeX Beamer

A previous question asked how to underline equations in color (1). However, many of the solutions suggested don't work in LaTeX Beamer. I also had difficulties finding ways for simple customisation, such as adjusting the thickness of the underline. Promising efforts for coloured underlining in Beamer have been made (2), but I have not seen a solution that satifies all of the following main criteria:

1. Underline both text and equations in colour in LaTex Beamer
2. Adjustable thickness of the underline
3. Compatibility with Beamer overlays, specifically in the way that overlaying underlines does not change vertical spacing within a slide
4. Long underlined expressions do not force an early line break, rather the underline stretches over two lines of text.

Here's code for an example slide

\documentclass{beamer}

\useinnertheme{default}

\begin{document}

\begin{frame}{Coloured Underlining}

Different parts of text can be underlined, using colours
such as green, red. The thickness of the underline can be set.

\vfill

Underlining is consistent with Beamer overlays.

\vfill

Underlining works as well in equations such
as $f(x) = \lambda\, e^x$ and

\begin{align*}
\mu = \frac{1}{2} \int_0^1 x f_{P_{ij}}(x)\,dx
+ \frac{1}{2} \int_0^1 f_{P_{ij}}(x)
\int_0^1 y \,f_{P_{ji}\vert P_{ij}}(y \mid x) \,dy \, dx.
\end{align*}

\vfill

Underlining longer expressions doesn't lead to lines
breaking early, but rather the underline stretches
across two lines of text.

\end{frame}
\end{document}


How can I implement an underline command to produce underlines in the slide as close as possible to the following graphic?

• Can you summarise which features are missing in gist.github.com/lucaswerkmeister/…? – user36296 Sep 20 '17 at 15:27
• There's two major problems: 1. It only works within equations (returns error when used in text) 2. scaling the thickness of the bar also changes the thickness of bars within the equation, for example the bar used in a fraction. The overlay syntax is very nice however, ideally a solution that also works with text has a similar functionality. – Felix Z. Hoffmann Sep 20 '17 at 16:25

As you have found out there are several techniques how to implement underlines and none (of those I know) fulfills all of your requirements.

Therefore I have written a wrapper \myul which selects one technique to use in this case based on the context (math mode or normal mode). With an optional argument you can manually specify color, thickness, depth and the technique. You can change these settings for the entire current group with the command \setmyul. For some options different values can be specified for math mode or text mode. For more details please see the comments in the code.

Sometimes two runs are required.

\documentclass{beamer}

\usepackage{soul}
\usepackage{pgfkeys}
\usepackage{mathstyle}
\usepackage{transparent}

\makeatletter

% ---------- key=value options ----------

\newif\if@myul@math@usedistance@
\newif\if@myul@text@usedistance@

\newcommand\@myul@text@depth{\SOUL@uldepth}
\newcommand\@myul@math@depth{\SOUL@uldepth}

\pgfqkeys{/myul}{
% thickness of the rule
thickness/.code={\setul{}{#1}},
%
% distance from baseline where to place the top of the rule
depth/.style={%
math depth=#1,
text depth=#1,
},
math depth/.code={%
\@myul@math@usedistance@false
\def\@myul@math@depth{#1}%
},
text depth/.code={%
\@myul@text@usedistance@false
\setul{#1}{}%
},
%
% distance from bottom edge of box where to place the top of the rule
% works only with command = box
distance/.style={%
math distance=#1,
text distance=#1,
},
math distance/.code={%
\@myul@math@usedistance@true
\def\@myul@math@distance{#1}%
},
text distance/.code={%
\@myul@text@usedistance@true
\def\@myul@text@distance{#1}%
},
%
% color in which to draw the rule (not the text)
color/.code={\setulcolor{#1}},
%
% which implementation technique to use
command/.style={%
text command=#1,
math command=#1,
},
%
text command/.is choice,
text command/soul/.code     ={\let\@myul@text@do=\@myul@soul},
text command/box/.code      ={\let\@myul@text@do=\@myul@box},
text command/primitive/.code={\let\@myul@text@do=\@myul@primitive},
%
math command/.is choice,
math command/soul/.code     ={\let\@myul@math@do=\@myul@soul},
math command/box/.code      ={\let\@myul@math@do=\@myul@box},
math command/primitive/.code={\let\@myul@math@do=\@myul@primitive},
%
% what to do if key is none of the above defined
.unknown/.code={%
% only process keys for which no full path has been provided
% TikZ documentation, page 900
\let\@myul@currentname=\pgfkeyscurrentname
\pgfkeysalso{%
command/\@myul@currentname/.try,
color/.lastretry=\@myul@currentname,
}%
\else
\def\pgfutilnext{\pgfkeysvalueof {/handlers/.unknown/.@cmd}#1\pgfeov}%
\pgfutilnext
\fi
},
}

% ---------- user interface ----------

\newcommand{\setmyul}[1]{%
\pgfqkeys{/myul}{#1}%
}

\newcommand<>{\myul}[2][black]{%
\begingroup
\setmyul{#1}%
\ifmmode
\expandafter \@myul@math@do
\else
\expandafter \@myul@text@do
\fi
#3{#2}%
\endgroup
}

% for auto completion in TeXstudio
\providecommand{\myul}[1]{}

% ---------- using soul package ----------
% based on soul package
% supports line break
% the text to be underlined can *not* be arbitrary TeX code
% see soul package documentation [November 17, 2003] page 5
% does *not* work in math mode

\newcommand<>{\@myul@soul}[1]{%
%https://tex.stackexchange.com/a/41693/120953
\let\set@color=\beamerorig@set@color
\let\reset@color=\beamerorig@reset@color
\alt#2{%
\ul{#1}%
}{%
\def\SOUL@ulcolor{\texttransparent{0.0}}%
\ul{#1}%
}%
}

% ---------- using boxes ----------
% based on:
% https://tex.stackexchange.com/a/9472/120953
% https://tex.stackexchange.com/a/1236/120953
% does *not* support line breaks

\newsavebox\@myul@box@tmpbox

\newcommand<>{\@myul@box}[1]{%
\ifmmode
\sbox\@myul@box@tmpbox{$\m@th \currentmathstyle #1$}%
\if@myul@math@usedistance@
\def\@myul@box@useddepth{\dimexpr-\dp\@myul@box@tmpbox-\@myul@math@distance-\SOUL@ulthickness}%
\else
\def\@myul@box@useddepth{\dimexpr-\@myul@math@depth-\SOUL@ulthickness}%
\fi
\else
\sbox\@myul@box@tmpbox{#1}%
\if@myul@text@usedistance@
\def\@myul@box@useddepth{\dimexpr-\dp\@myul@box@tmpbox-\@myul@text@distance-\SOUL@ulthickness}%
\else
\def\@myul@box@useddepth{\dimexpr-\@myul@text@depth-\SOUL@ulthickness}%
\fi
\fi
\usebox\@myul@box@tmpbox%
\alt#2{%
\llap{%
% \SOUL@ulcolor = \textcolor{<color>}
\SOUL@ulcolor{%
\rule[\@myul@box@useddepth]{\wd\@myul@box@tmpbox}{\SOUL@ulthickness}%
}%
}%
}{%
\rule[\@myul@box@useddepth]{0pt}{\SOUL@ulthickness}%
}%
}

% ---------- using TeX primitive ----------
% In plain TeX \underline is a primitive
% which can be used in math mode only.
% In LaTeX \underline is overridden
% so that it can be used outside of math mode, too.
% Either way, it does *not* support line breaks.
% Thickness and depth are *not* freely adjustable.
% thickness = $\theta$, distance to underline = $3\theta$
% where $\theta=\xi_8$ default rule thickness
% [The TeXbook, page 443, rule 10]
% default rule thickness can be changed with:
% \fontdimen8\textfont3=5pt
% default rule thickness is 0.4pt
% https://tex.stackexchange.com/a/167957/25264
% Changing the default rule thickness
% changes the thickness of fraction bars, too.
% Therefore this command ignores the thickness and depth options.
% You should avoid this method to avoid inconsistencies.

% based on https://gist.github.com/lucaswerkmeister/3f7672ee522f7e823cec63fdc85fd7aa
\newcommand<>{\@myul@primitive}[1]{%
% colored underline: https://tex.stackexchange.com/a/9477/25264
% transparent underline: https://tex.stackexchange.com/a/45601/25264
% switch between colored and transparent: http://mirrors.ibiblio.org/CTAN/macros/latex/contrib/beamer/doc/beameruserguide.pdf sections 9.3 and 9.6.1
% \SOUL@ulcolor = \textcolor{<color>}
\let\textcolor=\color
\alt#2%
{\SOUL@ulcolor\underline{{\color{black}#1}}\color{black}}%
{\transparent{0.0}\underline{{\transparent{1.0}#1}}\transparent{1.0}}%
}

\makeatother

% ---------- default settings ----------

\setmyul{
text command=soul,
math command=box,
}

% ---------- test ----------

\setmyul{math distance=.5ex}

\useinnertheme{default}

% based on https://tex.stackexchange.com/questions/14821/whats-the-proper-way-to-typeset-a-differential-operator
\newcommand{\dif}{\ensuremath{\operatorname{d}\!}}

\begin{document}

\begin{frame}{Coloured Underlining}

Different parts of text can be underlined, using colours such as \myul[color=green]{green}, \myul[red]{red}.
The \myul[thickness=2pt]{thickness} of the underline can be set.
Additionally, the \myul[depth=1pt]{depth} of the underline can be set, too.

\vfill

Underlining is consistent with \myul<2->{Beamer} \myul<3->[thickness=5pt]{overlays}.

\vfill

Underlining works as well in equations such
as $f(x) = \lambda\, e^x$ and

\begin{align*}
\mu = \myul<2->[red]{\frac{1}{2} \int_0^1 x \, f_{P_{ij}}(x) \dif x}
+ \frac{1}{2} \int_0^1 f_{P_{ij}}(x)
\int_0^1 \myul<3->[red, thickness=5pt]{y \,f_{P_{ji}\vert P_{ij}}(y \mid x)} \dif y \dif x.
\end{align*}

\vfill

Underlining longer expressions doesn't lead to \myul{lines breaking early, but rather the underline} stretches across two lines of text.

\end{frame}
\end{document}


Even though I use boxes as part of my logic, with my most recent EDIT, this does all including the very important auto-linebreak. It also handles math versus text mode seamlessly. The syntax is

\bunderline[<color>][<thickness>]{content}


and

\buonslide[<color>][<thickness>]<<beamer-slide-spec>>{content}


As it is, for text mode \bunderlines, I set the base of the underline at the same location (the base of a \strut) and grow upwards with increasing thickness. (If it grew downward from there, it would mess up the line spacing)

For math mode underlines, there is a constant 2pt gap between the content and the underline. Math mode underlines can be nested and preserve the current math style as well:

EDIT: Thanks to Jakun for reminding to add \m@th to the math mode \setbox0, to turn off any \mathsurround, in the event that it had been set to something other than 0pt.

The MWE:

\documentclass{beamer}
\usepackage{scalerel,stackengine}
\def\buthickness{1pt}
\def\budefaultcolor{black}
\makeatletter
\newcommand\bunderline[1][\budefaultcolor]{\def\bucolor{#1}\bunderlineaux}
\newcommand\bunderlineaux[2][\buthickness]{%
\ThisStyle{%
\ifmmode%
\setbox0=\hbox{\m@th$\SavedStyle#2$}
\stackunder[2pt]{\copy0}{\textcolor{\bucolor}{\rule{\wd0}{#1}}}%
\else%
\xdef\butmpthickness{#1}%
\prebunderlinewords#2 \endarg%
\fi%
}}
\def\prebunderlinewords#1 #2\endarg{%
\ifx\endarg#2\endarg\def\wdaugment{0pt}\else\def\wdaugment{.8ex}\fi%
\bunderlinewords#1 #2\endarg%
}
\def\bunderlinewords#1 #2\endarg{%
\setbox0=\hbox{#1\strut}%
\stackengine{0pt}{\copy0}{\textcolor{\bucolor}{%
\smash{\rule{\dimexpr\wd0+\wdaugment\relax}{\butmpthickness}}}}{U}{c}{F}{T}{S}%
\ifx\endarg#2\endarg\def\next{}\else\ \def\next{\bunderlinewords#2\endarg}\fi\next%
}
\newcommand\buonslide[1][black]{\def\butmpcolor{#1}\buonslideauxA}
\newcommand\buonslideauxA[1][\buthickness]{\def\butmpthickness{#1}\buonslideauxB}
\def\buonslideauxB<#1>#2{\onslide<#1>{%
\rlap{\bunderline[\butmpcolor][\butmpthickness]{\phantom{#2}}}}#2}
\makeatother
\useinnertheme{default}

\begin{document}

\begin{frame}{Coloured Underlining}
\setlength\mathsurround{2pt}
Different parts of text can be \bunderline{underlined}, using colours
such as \bunderline[green]{green}, \bunderline[red]{red}.
The \bunderline[black][3pt]{thickness} of the underline can be set.

\vfill

Underlining is consistent with \buonslide[red]<2->{Beamer}
\buonslide[red][2pt]<3->{overlays}.

\vfill

Underlining works as well in equations such
as $f(x) = \lambda\, e^x$ and

\begin{align*}
\mu = \bunderline[red]{\frac{1}{2} \int_0^1 x f_{P_{ij}}(x)\,dx}
+ \frac{1}{2} \int_0^1 f_{P_{ij}}(x)
\int_0^1 \bunderline[red]{
y \,f_{P_{\bunderline[cyan]{ji}}\vert P_{ij}}(y \mid x)} \,dy \, dx.
\end{align*}

\vfill

Underlining longer expressions doesn't \bunderline{lead to lines
breaking early, but rather the underline} stretches
across two lines of text.

\end{frame}
\end{document}


• shouldn't there be a \m@th in the math mode inside of the saved box to "turn of" \mathsurround or am I missing something? – jakun Sep 27 '17 at 7:54
• @jakun Yes, thank you. Since \mathsurround defaults to 0pt in beamer (and most classes), it isn't an issue here, but for greatest generality, it should be added. – Steven B. Segletes Sep 27 '17 at 10:20