# Highlight text and mathematical expressions with colored background

I'd like to have a function that I can use like a highlighter, both in text and in math mode. I wrote something that works but it's really slow and still causes problems in some situations. Here is the function:

%-------------------------Highligh-------------------------%

\newif\ifhighlight
\highlighttrue

\definecolor{colorA}{rgb}{1,1,0.5}
\definecolor{colorB}{rgb}{0.85,0.85,1}

\newlength{\fboxseptemp}

\newcommand{\hl}[2][colorA]{%
\ifhighlight%
\setlength{\fboxseptemp}{\the\fboxsep}%
\setlength{\fboxsep}{0pt}%
\ifmmode%
\text{\hl[#1]{$#2$}}%
\else%
$\mathrlap{\text{\smash{\colorbox{#1}{\phantom{#2\vphantom{\strut}}}}}}$%
\setlength{\fboxseptemp}{\fboxseptemp}%
#2%
\fi%
\else%
#2%
\fi}

%-------------------------Highligh-------------------------%


I can use it like this:

For sets $A$ and $B$ let $\hl{B^A}$ denote the \hl{set of all mappings} from $A$ to $B$.


It works fine in many situations but it's not perfect. First of all it compiles really slowly. In some situations the colored background boxes are to wide. This happens if latex shrinks a text to fit it in a line. The box is then as long as the original (not shrunk) text and thus a little bit longer than the text that is displayed. Also it cannot deal with line breaks. Another problem are ligatures if they are before the highlighting.

\hl{empty}.


is formated exactly as

empty.


The dot is moved towards the y and overlaps with the colored box a little bit as it should. But

f\hl{inite}


produces a different result than

finite


The f and the i are not merged correctly and the colored box covers the f a little bit. Does anybody know a more elegant, fast and stable solution for that problem?

This should be faster than using \colorbox. It avoids the shrinkage and line breaking by simply not shrinking or breaking. Of course, you can't use this for more than one line. (You could parse the text and highlight each word separately.)

I added \hlleft and \hlright to highlight parts of words without changing the spacing.

\documentclass{article}
\usepackage{xcolor}
%-------------------------Highligh-------------------------%

\newif\ifhighlight
\highlighttrue

\definecolor{colorA}{rgb}{1,1,0.5}
\definecolor{colorB}{rgb}{0.85,0.85,1}

\newsavebox{\tempbox}

\newcommand{\hl}[2][colorA]{% #1 = color (opptional), #2 = text
\ifhighlight%
\ifmmode\savebox{\tempbox}{$#2$}%
\else\savebox{\tempbox}{#2}%
\fi
\leavevmode\rlap{\color{#1}\rule[-\dp\tempbox]{\wd\tempbox}{\dimexpr \ht\tempbox + \dp\tempbox}}%
\usebox{\tempbox}%
\else
#2%
\fi}

\newsavebox{\partbox}

\newcommand{\hlleft}[3][colorA]{% #1 = color (opptional), #2 = text, #3 = part highlighted
\ifhighlight%
\ifmmode\savebox{\tempbox}{$#2$}%
\savebox{\partbox}{$#3$}%
\else\savebox{\tempbox}{#2}%
\savebox{\partbox}{#3}%
\fi
\leavevmode\rlap{\color{#1}\rule[-\dp\partbox]{\wd\partbox}{\dimexpr \ht\partbox + \dp\partbox}}%
\usebox{\tempbox}%
\else
#2%
\fi}

\newcommand{\hlright}[3][colorA]{% #1 = color (opptional), #2 = text, #3 = part highlighted
\ifhighlight%
\ifmmode\savebox{\tempbox}{$#2$}%
\savebox{\partbox}{$#3$}%
\else\savebox{\tempbox}{#2}%
\savebox{\partbox}{#3}%
\fi
\leavevmode\rlap{\color{#1}\hspace{\dimexpr \wd\tempbox - \wd\partbox}%
\rule[-\dp\partbox]{\wd\partbox}{\dimexpr \ht\partbox + \dp\partbox}}%
\usebox{\tempbox}%
\else
#2%
\fi}

\begin{document}
First a \hl{simple} test.
$x=a\quad\hl{\forall a}$
\par\hl{test}
\par empty. \hl{empty}. \hlleft{empty.}{empty}
\par finite f\hl{inite} \hlright{finite}{inite}
\end{document}


• You're right, it's really a lot faster, thanks! But it doesn't solve any of the formatting problems. Actually there are more now. Try Le\hl{bes}gue. "Le and "bes" are separated by some white space (they are not with my version). Also there is a problem with indentation. Try using \hl{test} at the beginning of a new paragraph. The colorbox is where the text should be but the text is in the next line. Finally there is the ligature problem. Now it doesn't even handle \hl{empty}. correctly. Compare the two versions. With mine the dot is moved towards the y a little bit as it should. – Mario Jun 18 '15 at 7:55
• I fixed the paragraph problem, but the only way to highlight parts of words without changing the spacing is to add specialized macros. – John Kormylo Jun 18 '15 at 15:07
• You can't have it all it seams :/. This is such an easy task with MS Word but almost impossible with Latex. – Mario Jun 18 '15 at 15:08
• Might there be a way to do it in two compilation runs? – Mario Jun 18 '15 at 15:14
• Using xstring you could automatically break the word into highlighted and non-highlighted sections, but the widths of the sections won't add up to equal the entire word. – John Kormylo Jun 18 '15 at 15:25