11

When using link boxes from hyperref, following punctuation is not fully visible.

MWE:

\documentclass{article}
\usepackage{hyperref}
\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

What is the easiest/nicest solution for this (apart from not using link boxes)?

A possibility is to add the thinspace automatically. I tried

\usepackage{xpatch}
\xapptocmd{\ref}{\,}{}{}

but that doesn't work. Also, I would have to patch \cref,\Cref,\hyperref,\url, \cite.

I would like to avoid \newcommand{\myref}[1]{\ref{#1}\,} (although that does work), because I don't want to change the standard way of referencing in the document. Also, such a solution would not work for parencites where the parentheses are added by \citep (and/or other \cite variants).

It might also help to put the punctuation on top of the box instead of behind.

However, the best solution (imo) is to change the hyperref box drawing command to include some extra whitespace before and after a link (outside of the box).


Extra MWEs

with natbib and \citep:

\documentclass{article}
\begin{filecontents}{\jobname.bib}
@book{author_book,
  title = {Book's title},
  author = {Author, Some},
  year = {2005},
}
@book{other_book,
  title = {Book's title},
  author = {Writer, A},
  year = {2010},
}
\end{filecontents}
\usepackage[round]{natbib}
\usepackage{hyperref}
\makeatletter
\renewcommand\hyper@natlinkbreak[2]{#1}
\makeatother
\begin{document}
\fontfamily{ptm}\selectfont % using ptm makes it worse
\section{My section}
\label{sec:my}
See also \citep{author_book,other_book} vs (\,\hyperref[sec:my]{Author, 2005}\,; \hyperref[sec:my]{Writer, 2010}\,).
\bibliographystyle{plainnat}
\bibliography{\jobname}
\end{document}

with apalike:

\documentclass{article}
\begin{filecontents}{\jobname.bib}
@book{author_book,
  title = {Book's title},
  author = {Author, Some},
  year = {2005},
}
@book{other_book,
  title = {Book's title},
  author = {Writer, A},
  year = {2010},
}
\end{filecontents}
\usepackage{apalike}
\usepackage{hyperref}
\begin{document}
\fontfamily{ptm}\selectfont % using ptm makes it worse
\section{My section}
\label{sec:my}
See also \cite{author_book,other_book} vs (\,\hyperref[sec:my]{Author, 2005}\,; \hyperref[sec:my]{Writer, 2010}\,).
\bibliographystyle{apalike}
\bibliography{\jobname}
\end{document}

enter image description here

  • 2
    You could try something like \hypersetup{ colorlinks, linkcolor={red!50!black}, citecolor={blue!50!black}, urlcolor={blue!80!black} } instead (requires xcolor) – Steven B. Segletes Sep 12 '17 at 11:18
  • @StevenB.Segletes that looks indeed much nicer, however the boxes are mandatory (but spacing is not restricted). – Marijn Sep 12 '17 at 12:19
  • The how about \usepackage[pdfborder={0 0 .05}]{hyperref}? – Steven B. Segletes Sep 12 '17 at 12:30
  • 1
    Since I rarely use Adobe Acrobat Reader, I'm never bothered by those boxes. – egreg Sep 18 '17 at 9:53
  • 3
    Well, that's irrelevant: when you'll print the document you'll not see the boxes and you'll have unwanted spaces. – egreg Sep 18 '17 at 10:59
10
+100

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.

  • Very nice answer. I'll wait with accepting to see if anyone knows how to control the size of the box, otherwise I'll pick this one as most informative. – Marijn Sep 19 '17 at 8:47
  • @Marijn I noticed a simple way to control the size of the box; added it to the end of the answer. – ShreevatsaR Sep 19 '17 at 15:18
  • That is exactly what I need :) When using this, the box occasionally becomes a bit too small vertically, but that can be solved quick and dirty by adding invisible zero-width somewhat big elements in the link, like \vphantom{$X^1_1$}. – Marijn Sep 20 '17 at 7:33
  • Kudos for finding \setpdflinkmargin/the pdflinkmargin option! Proofed to actually not be my (unrelated) problem of too big blocks :) – stefanct Jul 5 '19 at 10:37
4

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

  • 1
    That's useful; welcome to TeX.SE! – ShreevatsaR Sep 15 '18 at 21:04
3

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

  • Could this be generalized for parencites, such as \usepackage[round]{natbib} [...] \citep{mycitekey}, or non-natbib customized bibtex styles? I didn't want to make the MWE to complex, therefore I included only ref and hyperref and asked about redefining the box drawing command in the question (see the I would like to avoid part) . – Marijn Sep 18 '17 at 10:24
  • @Marijn Perhaps if you generalize your MWE to include use cases, I could have a look. I could say that \url probably will not work with a conversion, as the argument is processed in verbatim, and this technique will therefore fail for it. – Steven B. Segletes Sep 18 '17 at 10:29
  • @steven-b-segletes I've added two MWEs. – Marijn Sep 18 '17 at 10:56
  • 1
    Sorry, but doing so you lose \ref* which can be quite important with hyperref. Beware also that \ref is defined with \DeclareRobustCommand when hyperref is loaded, so \letltxmacro should be used. – egreg Sep 18 '17 at 10:58
  • 3
    I would discourage this: keep in mind that the color boxes are only displayed on screen; printing the document would reveal the horrible pre-punctuation spaces – Bordaigorl Sep 18 '17 at 11:04
2

Run it with xelatex or lualatex:

\documentclass{article}
\usepackage{hyperref}
\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

  • 2
    This indeed solves the punctuation problem, but it looks arguably worse than before - I didn't think that was possible :) – Marijn Sep 18 '17 at 10:28
  • (1) If I understand correctly this is just the same as the OP's file, just compiled with xelatex rather than pdflatex. Is that right? (2) I get the same result with pdflatex and lualatex, and a different result (as above) with xelatex. – ShreevatsaR Sep 18 '17 at 19:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.