Link boxes obscure punctuation

What are these boxes?

At heart, TeX is a typesetter: it is concerned with deciding where characters should be positioned, in order to obtain pleasing output on a printed page. In fact, TeX is well over a decade older than the PDF format, from a time when visualizing typeset output on a screen did not exist. So as far as the “core” of TeX is concerned, what it typesets (and what you'll get if you print your document) has no red boxes to indicate links:

hidelinks

So why do you see red boxes in your PDF viewer? You see them because the hyperref package redefines all the LaTeX cross-referencing macros such that (in particular, at its default settings) links are inserted into the PDF stream as PDF annotations, and boxes show up (superimposed on the above output!) when viewed in certain PDF viewers. Some PDF viewers do not even implement showing these boxes (or at least, have a different default).

Even if they do show boxes, the appearance can depend on the PDF viewer version, operating system, screen resolution, zoom level, etc. For example, with the MWE in the question, this is what I see on my computer:

default settings

(Click on the image and zoom to see it pixel-for-pixel: screenshot from Acrobat Reader on macOS Sierra at zoom level 200%.) Here, the problem is not as serious as in the question. And the appearance seems even better if we change the link colour (e.g. for blue, change the \usepackage{hyperref} line to \usepackage[linkbordercolor={0 0 1}]{hyperref}).


Why not add spaces?

If you tried to add additional spaces to account for the link boxes, you would be asking TeX to change the typesetting (position of punctuation) away from what it considers best. As a result, if you printed your document, or viewed it in one of the PDF viewers that don't show the boxes, you would have ugly extra spaces.

There is yet another reason not to fiddle with the spaces, even if everyone is using a PDF viewer that shows the boxes. By default, the link boxes are always displayed as a fixed number of pixels wide, no matter the zoom level of the PDF document. This means that as you make the text larger and larger on your screen (more pixels per character), the boxes become smaller relative to the text. So although when you view the PDF at 50% zoom the boxes may appear thick and have quite an overlap:

zoom 50%

So you may think that you need to add X ems of space after the box, to have the following punctuation not overlap. But if someone has a bigger or higher-resolution monitor and zooms in the text, what they'll see is quite different:

zoom 2400%

which means that you'll need to add a much tinier space to displace the comma relative to the box, and if you added space appropriate for the smaller zoom level, that would suddenly be too wide here.


What can you do instead?

So IMO (as you also agreed in a comment) a better solution would be to keep the typesetting the same, but change the nature of the PDF annotation, so that the boxes appear more suitably in the relevant PDF viewer.

If you feel that the link boxes are going to appear bad for a significant fraction of viewers of your PDF, then the easiest thing you can do is indicate links differently: look up the colorlinks option in the hyperref manual (which itself uses this option). If you really want the boxes though, then what you need to do is change the annotation that goes into the PDF. Of course to do this, first you need to determine what the “proper” annotation should look like.

To get a hint of how annotations are implemented by hyperref, we can look at its code (following the trail of linkbordercolor and specifically for the pdfTeX engine), where we find a \def\find@pdflink#1#2 in hpdftex.def, whose last few lines look suggestive:

\def\find@pdflink#1#2{%
  % […snip… some lines omitted here]
  \Hy@StartlinkName{%
    \ifHy@pdfa /F 4\fi
    \Hy@setpdfborder
    \ifx\@pdfhighlight\@empty
    \else
      /H\@pdfhighlight
    \fi
    \ifx\CurrentBorderColor\relax
    \else
      /C[\CurrentBorderColor]%
    \fi
  }\Hy@testname
  \expandafter\Hy@colorlink\csname @#1color\endcsname
}

The actual position of the rectangle appears to be determined by the specific DVI/PDF driver: pdfTeX, XeTeX, dvips, all have slightly different positioning, and I'm not sure how to control that. But there are other options; see below.

Looking up the PDF 1.5 specification (warning: 14MB, 1172-page PDF), we can find some details of what the options are, at around section 8.4.3 Border Styles. Putting the two together, we can see that we can change the PDF annotations by adding stuff after the /C[\CurrentBorderColor] \fi bit.

For example, we can specify the width of the border to be 4 times its default value, to make the problem worse. Below, the /BS <</W 4>> (BS stands for Border Style and W for Width) is the new stuff added to the PDF annotation (by patching the macro we saw above), documented in TABLE 8.13 Entries in a border style dictionary of the PDF spec:

\documentclass{article}
\usepackage{hyperref}

\usepackage{etoolbox}
\makeatletter
\patchcmd{\find@pdflink}{
      /C[\CurrentBorderColor]%
    \fi
}{
      /C[\CurrentBorderColor]%
    \fi
    /BS <</W 4>>
}{}{}
\makeatother

\begin{document}
\section{My section}
\label{sec:my}
As seen in \ref{sec:my}, \texttt{hyperref} obscures punctuation, especially with \hyperref[sec:my]{a dot}. It works better with \hyperref[sec:my]{trailing whitespace}\,.
\end{document}

This results in:

width 4

Conversely, we can decrease the width as much as 0.5, with /BS <</W 0.5>>:

width 0.5

(To be honest I see no difference on my computer between the default width 1 and width 0.5, but you can play with it on yours and see if it makes a difference.)

You can also change the style to dashed, with something like /BS <</S /D /D [2 3]>>:

dashed 2-3

(The [2 3] means dashes that are 2 points long, alternating with gaps that are 3 points long… you can change the parameters and also the width, with something like /BS <</W 1.5 /S /D /D [3 4]>> or whatever.) You can experiment with all these parameters to find something you like best. For example, /BS <</W 2 /S /D /D [8 8]>> results in:

dashed 2-8-8

You can also change the style to underlined, with /BS <</S /U>>:

underline

You can explore more by reading the PDF spec and/or examining the generated PDFs, to see what else you can edit where, to control what aspects of the appearance. Note that not all PDF viewers support all options in the PDF spec, so you need to experiment with the actual PDF viewers your document's “users” will use.

Once you know exactly what kind of annotation (supported by the PDF viewer) you'd like to have in your document, patching hyperref to achieve that becomes a more specific problem.


Edit: Although it is not documented in the hyperref manual, in the code a pdflinkmargin option is present, which controls how much margin is added on all sides, around the content. So, compared to the default (above), which appears to be 1pt, this is what I get if I set it to 0pt:

\documentclass{article}
\usepackage{hyperref}
\setpdflinkmargin{0pt}

\begin{document}
\section{My section}
\label{sec:my}
As seen in \ref{sec:my}, \texttt{hyperref} obscures punctuation, especially with \hyperref[sec:my]{a dot}. It works better with \hyperref[sec:my]{trailing whitespace}\,.
\end{document}

pdflinkmargin 0pt

Just to illustrate the effect, we can try exaggerated values like 10pt:

pdflinkmargin 10pt

or -1pt:

pdflinkmargin -1pt

This is like any TeX length, so you are not constrained to an integer number of pt and you can use mm or other units. Now that we know what to search for, we can find more documentation about this in this answer by Heiko Oberdiek (one of the authors of hyperref). It explains how this works, and some limitations (it works with pdfTeX/LuaTeX/dvips drivers, but does not work with dvipdfm/XeTeX drivers). You can set it with \hypersetup{pdflinkmargin=0pt} instead of \setpdflinkmargin{0pt}. It is also documented in the hyperref README.


The following is a much simpler implementation of ShreevatsaR's solution with border styles. Simply add the following line below \usepackage{hyperref} to achieve dotted boxes:

\hypersetup{ pdfborder={0 0 1 [1 2]} }

The first two numbers specify radii for rounded corners. Since they are ignored by most viewers, you might as well set them to zero. The third number is the border width, which can be a decimal. The numbers in the square brackets specify a dashing pattern: here 1-unit dashes with 2-unit spaces.

The more sophisticated /BS commands described in ShreevatsaR's solution can be specified with:

\hypersetup{ pdfborderstyle={/W 1 /S /D /D [1 2]} }

In either case, the output in Okular looks as follows:

enter image description here


This answer is not really suitable for printed output, as Bordaigorl points out, because of the space added will create unsightly gaps in printed output (where the hyperref boxes are absent). I even deleted the answer at one point for that reason.

However, the OP asserts that for the application intended, making it look good for online viewing takes precedence over the appearance on paper.

Egreg also points out that with the current approach, \ref* becomes broken. I have not taken the time to look further into that.

All that said, here was previously deleted answer:


Here, I save the meanings of \ref and \hyperref and redefine them to add a trailing \,. I am not sure if I have covered all the syntax variations of \hyperref.

\documentclass{article}
\usepackage{hyperref}
\let\svref\ref
\let\svhyperref\hyperref
\AtBeginDocument{
  \renewcommand\ref[1]{\svref{#1}\,}
  \renewcommand\hyperref[2][]{\svhyperref[#1]{#2}\,}
}
\begin{document}
\section{My section}
\label{sec:my}
As seen in \ref{sec:my}, \texttt{hyperref} obscures punctuation, especially with \hyperref[sec:my]{a dot}. It works better with \hyperref[sec:my]{trailing whitespace}.
\end{document}

enter image description here