# underline omitting the descenders

I'm very well aware that it is considered best practice not to use underlining other than on typewriters and in handwriting. But sometimes it is needed nonetheless.

In my opinion the typographically least offending way to underline in print is to leave out the descenders. This is also how I learned to do it in handwriting. Very few fonts offer a pre-made underlined variant, but some text-processors (e.g. OS X text-engine) do -- depending on the font used -- an acceptable job at emulating this effect:

How would I tweak any of the existing ways/packages for underlining to do the same?

As a bonus, I'd like to be able to tweak the behaviour (extent of the omitted part, apply to which letters) per font and text style, preferably working with XeLaTeX.

-

We could do for each letter:

• Produce the underlining
• Overwrite the line with the same but bolder letter or with a left and right shifted one, but in background or white color
• Write the letter

So we would get an underline with matching gaps.

Here I modified the soul approach of Marco in this way, just for a demonstration what I mean, which could be improved (boldness, loop):

\setcounter{errorcontextlines}{999}
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[latin1]{inputenc}
\usepackage{soul}
\usepackage{color}
\makeatletter
\newcommand*{\whiten}[1]{\llap{\textcolor{white}{{\the\SOUL@token}}\hspace{#1pt}}}
\DeclareRobustCommand*\myul{%
\def\SOUL@everyspace{\underline{\space}\kern\z@}%
\def\SOUL@everytoken{%
\setbox0=\hbox{\the\SOUL@token}%
\ifdim\dp0>\z@
\raisebox{\dp0}{\underline{\phantom{\the\SOUL@token}}}%
\whiten{1}\whiten{0}%
\whiten{-1}\whiten{-2}%
\llap{\the\SOUL@token}%
\else
\underline{\the\SOUL@token}%
\fi}%
\SOUL@}
\makeatother
\begin{document}
\sffamily\Huge
\myul{jumping quickly}
\end{document}


-
I really like your approach, but there's still a problem when the character's stem is even more narrow than the gap between descender and underline. Cf when removing \sffamily from your example. Any ideas how to solve this? – Florian Dec 3 '11 at 10:44
@Florian You could add \whiten{0}\whiten{-0.5} to get more removed. Or whiten in small steps in a loop. I'll add this when I've got time for it. – Stefan Kottwitz Dec 3 '11 at 11:05
@StefanKottwitz I'd love to be able to do this with a thicker line. I tried simply using \ul (rather than underline) from soul and changing the thickness but that doesn't seem to work. Is that because I'm using it within the scope of a redefinition of the soul macros? Would it require a complete re-write of this to provide user set underline thickness? – Scott H. Jun 12 '12 at 0:33
I think this would make a fine package or addition to soul, perhaps adding some easy ways to tune the behaviour for the font used... – Florian Jun 26 '12 at 12:09
The \raisebox makes the line higher than necessary. It can be fixed by either the optional argument of \raisebox: \raisebox{\dp0}[\height]{\underline{\phantom{\the\SOUL@token}}}. Or it can be done in a simpler way without \raisebox: \underline{\kern\wd0}. – Heiko Oberdiek Jun 4 '14 at 1:26

here a solution which works also with pdflatex and using the advantages of the package soul:

\setcounter{errorcontextlines}{999}
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[latin1]{inputenc}
\usepackage{soul}
\makeatletter
\DeclareRobustCommand*\myul{%
\def\SOUL@everyspace{\underline{\space}\kern\z@}
\def\SOUL@everytoken{%
\setbox0=\hbox{\the\SOUL@token}%
\ifdim\dp0>\z@
\the\SOUL@token
\else
\underline{\the\SOUL@token}%
\fi}
\SOUL@}
\makeatother
\begin{document}
\myul{jumping quickly}

\end{document}


-
Is there any way to fine-tune this code some more to take into account that the descenders of p and q take up less (horizontal) space below the line than do g, j, and y? – Mico Dec 2 '11 at 15:02
@Mico -- remember that tex doesn't know anything about the shape of the letters, only the dimensions of the defined bounding box. so an automatic adjustment is currently out of the question. but too bad -- it would be a really nice feature. – barbara beeton Dec 2 '11 at 17:47
@barbarabeeton: Thanks, Barbara, for this refresher. (I had indeed temporarily forgotten this basic fact!) I guess the subject of how to provide more information than just the dimensions of a character's bounding box might be tackled one day by lua(la)tex programmers. :-) – Mico Dec 2 '11 at 18:21
@Mico: I think it is possible by using a virtual font but I don't know how ;-) – Marco Daniel Dec 2 '11 at 19:46

Simply because I found it useful here is a modification of Stefans answer above that lets you control the depth, thickness and width of the underline. This might be useful, for example, with a larger or bolder font. The syntax is: \varul<width>[depth][thickness]{stuff} where:

• <width> is optional and given as a multiple of 1/100 em, e.g. <10> would give a gap width of 0.1em. The default value is 5
• [depth] is optional and is given as a positive value (including units) that specifies the distance below the baseline to draw the underline. The default value is 0.2ex.
• [thickness] is optional and is given as a positive value (including units) specifying the thickness of the underline. The default value is 0.1ex
• The fourth, mandatory, argument is what you want underlined.

This will work across paragraphs and linebreaks but may change the spacing very slightly.

\documentclass{article}
\usepackage{soul}
\usepackage{xcolor}
\usepackage{xparse}
\makeatletter

\ExplSyntaxOn
\cs_new:Npn \white_text:n #1
{
\fp_set:Nn \l_tmpa_fp {.01}
\fp_mul:Nn \l_tmpa_fp {#1}
\llap{\textcolor{white}{\the\SOUL@syllable}\hspace{\fp_to_decimal:N \l_tmpa_fp em}}
\llap{\textcolor{white}{\the\SOUL@syllable}\hspace{-\fp_to_decimal:N \l_tmpa_fp em}}
}
\NewDocumentCommand{\whiten}{ m }
{
\int_step_function:nnnN {1}{1}{#1} \white_text:n
}
\ExplSyntaxOff

\NewDocumentCommand{ \varul }{ D<>{5} O{0.2ex} O{0.1ex} +m } {%
\begingroup
\setul{#2}{#3}%
\def\SOUL@uleverysyllable{%
\setbox0=\hbox{\the\SOUL@syllable}%
\ifdim\dp0>\z@
\SOUL@ulunderline{\phantom{\the\SOUL@syllable}}%
\whiten{#1}%
\llap{%
\the\SOUL@syllable
\SOUL@setkern\SOUL@charkern
}%
\else
\SOUL@ulunderline{%
\the\SOUL@syllable
\SOUL@setkern\SOUL@charkern
}%
\fi}%
\ul{#4}%
\endgroup
}

\makeatother
\begin{document}

\varul{\Huge jumping quickly}\par\smallskip
\varul[1pt][1pt]{\Huge jumping quickly}

\end{document}

-
Does this require TeX 2012, as I am getting an Undefined control sequence with TeXLive2011? – Peter Grill Aug 14 '12 at 0:11
@PeterGrill Hi Peter I'm not familiar with TeXLive, nor with how it works. Likely, you're getting an undefined control sequence on \int_step_function:nnnN which was a recent addition (~June) to expl3. If you are able to update to the most recent version of expl3, then that should take care of the problem (assuming that I'm right about the control sequence). – Scott H. Aug 14 '12 at 5:37
Just for the sake of completeness: xparse loads the expl3 package. A number of the cs's used above are actually from the expl3 package, despite it not having been loaded explicitly. – Scott H. Aug 14 '12 at 5:52
Very nice solution! Perhaps you would consider packaging it and put it on CTAN? – Florian Aug 16 '12 at 9:37

Here is a solution using contour and ulem packages.

IMO this produces a very good looking underline, specialy for title underlining:

\documentclass{article}

\usepackage[outline]{contour}

\usepackage{ulem}
\normalem % use classical emph

\newcommand \myul[4]{%
\begingroup%
\renewcommand \ULdepth {#1}%
\renewcommand \ULthickness {#2}%
\contourlength{#3}%
\uline{\phantom{#4}}\llap{\contour{white}{#4}}%
\endgroup%
}

\newcommand \myulline[4]{%
\begingroup%
\renewcommand \ULdepth {#1}%
\renewcommand \ULthickness {#2}%
\contourlength{#3}%
\noindent\rlap{\uline{\hspace{\textwidth}}}\contour{white}{#4}%
\endgroup%
}

\begin{document}
\bfseries

\Huge
\myulline{5pt}{1pt}{2pt}{Chapter Eight}

\vspace{1cm}

\normalsize
\normalfont

Test. \myul{2pt}{0.5pt}{1pt}{Quit jumping quickly!} Test.

Test. \myul{1.2pt}{0.5pt}{0.5pt}{Quit jumping quickly!} Test.

\end{document}


Output:

Close up:

As drawback, the underline depth cannot be very close to baseline because it can be hidden by the contour.

-
Oh, how we need a screenshot here... – jonalv Oct 5 '12 at 11:41
Done. I was waiting for a minimum of 10 points of reputation to be able to post images, this was my first contribution :) – CDSousa Oct 5 '12 at 13:35
Quite a nice first contribution! Hoping to see more of this :). This is a really nice underlining for titles -- as you said -- especially with the line extending to the right like in your example. For regular paragraph text, however, I'd indeed like the underline to be closer to the baseline. – doncherry Oct 6 '12 at 4:52
@matheburg Done. Thanks. – CDSousa Jun 3 '14 at 18:48

I'm using the following adaption of CDSousa's answer, for two reasons: firstly, XCharter + contour for some reason looks more coarse than the other text; secondly, to allow for close underlining (the drawback pointed out by CDSousa):

\usepackage{ulem}
\normalem % use classical emph
\usepackage{color}
\usepackage{pgffor}
\newcommand\myul[4]{% arg 1: underline depth; arg 2: underline thickness; arg 3: space around descenders in pt (!)
\begingroup%
\renewcommand\ULdepth{#1}%
\renewcommand\ULthickness{#2}%
\uline{\phantom{\smash{#4}}}%
\foreach \hshift in {0.0, 0.1, ..., #3}{%
\foreach \upshift in {-0.4, -0.3, ..., 1.0}{%
\llap{\color{white}\raisebox{\upshift0pt}[0pt]{#4}\hspace{\hshift0pt}}%
\llap{\color{white}\raisebox{\upshift0pt}[0pt]{#4}\hspace{-\hshift0pt}}%
}%
}%
\llap{#4}%
\endgroup%


Example: \myul{1.75pt}{.5pt}{2}{Blupp of (that's \emph{of}, not \emph{off}, of course) a great Synopsis} has underline depth 1.75pt, underline thickness .5pt, and spacing 2pt, and looks like

-