[Tex/LaTex] Cross-reference packages: which to use, which conflict

cross-referencingincompatibilitypackages

Inspired by my earlier question Theorem packages: which to use, which conflict?, here is another similar question.

There are many different packages for making cross references. Among them hyperref, cleveref, varioref, theoremref, nameref… The ntheorem package defines its own cross-referencing command for theorems…

Which collection of packages provides which kind of functionality, and which packages cause conflicts with each other?

Best Answer

Preliminaries

In this answer, I'll be discussing how to go about creating cross-references to "objects" such as "Theorem 2", "Lemma 3", "Page 7", and "Section 4". Each object is assumed to be associated with a \label command; for instance, some important numbered theorem may be associated with \label{thm:important} and a numbered \section directive may be associated with \label{sec:results}.

Classes of cross-references: Static, semi-dynamic, and fully dynamic

  • Static or hard-coded cross-references. As the name "static" implies, these cross-references are hard-coded strings of the form Theorem~2 and Section~4. Other examples are in the next paragraph, in the final section, and the preceding lemma.

    • Advantages:
      1. Trivially simple to implement.
      2. Requires no extra packages (or even TeX commands).
      3. Doesn't even require use of the \label commands. Extremely flexible.
    • Disadvantages:
      1. Requires a lot of care when first writing the document. For example, static references to the numbers of still-to-come equations, theorems, etc. can only be finalized after the rest of the document is completed.
      2. Serious risk of cross-references becoming stale or incorrect if the objects' numbers and/or types change later on. E.g., if an object named "Theorem 2" eventually becomes "Lemma 3", both the number and the type of the object are changed. The staleness risk is especially serious for cross-references to page numbers.
      3. Requires a willingness to do a lot of follow-up editing during the authoring process. Associated risk that this follow-up editing won't catch all required changes to the hard-coded cross-references.
      4. No built-in method for making these static cross-references into hyperlink targets should the author(s) wish to do so. (Actually, there is a way, via the \hyperlink and hypertarget commands of the hyperref package. However, it's much much easier to simply use \label and various \ref commands along with the hyperref package.)
  • Semi-dynamic cross-references. These include the TeX/LaTeX \ref and \pageref commands. I call this method semi-dynamic rather than fully dynamic because it automates the numbering of the objects in question but hard-codes their types (Theorem, page, section, ...).

    • Advantages:
      1. Almost as simple as the (fully) static method.
      2. Avoids risks (1) and (2) of the static method, at least for the number part of the cross-reference.
      3. If only a few cross-references are needed in the document, this method is fully sufficient.
      4. By loading the hyperref package, the cross-references' numbers can be made into hyperlink targets as well.
    • Disadvantages:
      1. If you have cross-references to lots of objects at a time, say to "equations (2), (3), (5), (7), and (8)", typing all those \ref{} commands quickly becomes very tedious as well as error-prone.
      2. If you decide to change the type of an item being cross-referenced, say from "Theorem" to "Proposition", be prepared to do a lot of hand-editing of the hard-coded parts of the cross-references.
  • Fully dynamic cross-references. Both the object's type and its number are generated by LaTeX.

    • Advantages:
      1. Avoid all risks noted above of the static cross-referencing method.
      2. Saves a lot of time when cross-referencing tasks are complex.
    • Disadvantages:
      1. Requires loading one or more additional LaTeX packages.
      2. Not all object types may already be defined by the package(s), requiring the author to add these object types by hand.
      3. Because the packages perform some fairly complex operations, there's a risk of unwanted interactions and incompatibilities with other LaTeX packages.

Which packages provide which kinds of cross-referencing facilities?

  • amsmath. Provides the \eqref command to cross-reference numbered equations.

    There are two important advantages to typing \eqref{eq:einstein} instead of (\ref{eq:einstein}):

    1. You needn't remember to place parentheses around the cross-referenced equation number, and
    2. The output of \eqref (including the parentheses) is always set in an upright font shape. This feature is useful because cross-references to equations may occur in some text block that's set in italics (such as in the body of a theorem statement). By (near-universal?) convention, equation numbers and their parentheses should generally be typeset in an upright font shape regardless of the font shape of the surrounding text. It's quite handy not having to keep track of whether a cross-reference to an equation occurs in an italic text block or a "regular" (i.e., upright font shape) text block.
  • prettyref. Provides the command \prettyref.

    An important step towards fully dynamic cross-references. It works by relying on information contained in the object's \label to infer the object's type. However, this approach has some serious limitations. Quoting from its manual:

    Labels in the document must be of the form format:name where the string format is used to determine the [object's type]. Do not use the character : anywhere within the label except to separate format from name. format:name must be unique for it is used as the label.

    In short, if you need to change the object's type from "theorem" to "proposition", you'll also need to change its label. This negates some of the advantages of using this package (in my view). A second problem can arise if the babel package is loaded with the option french, as this makes the : character "active" (in the TeX-specific sense of the word). For a work-around in case you need to load both prettyref and babel-french, see the query prettyref bug when used with babel-french and especially Enrico Gregorio's answer.

  • varioref. Provides the commands \vref and vpageref. Its stated aim is to provide "intelligent page references." From the introduction of the package's user guide:

    The \vref command refers to labels in the same way as does \ref, but if the thing referred to is on a different page, the result will be decorated with "on the facing page" or "on page ", and so on, as appropriate. The \vpageref command similarly decorates a page number; there are also commands \vrefrange and \vpagerefrange for ranges of labels.

    Very useful if you need to provide page location information automatically with each cross-reference.

  • smartref. This package partially extends the functionality of varioref, enabling not just the page of a \label to be recorded, but the value of arbitrary other counters (such as the present chapter). This can be immediately used to add "in chaper N" to cross-references or, with some additional logic (example), to produce a varioref-style "in the next/previous chapter" call-out.

  • fancyref. Another step towards fully dynamic cross-referencing. Provides the commands \fref (and, for the beginning of a sentence, \Fref} for various pre-defined object types. It requires the use of specific label prefixes (e.g., chap, sec, eq, fig, etc.) to inform it about the object's type. Quite a few language-specific adaptations are available if it's used together with babel. Fully compatible with the varioref package.

    If you wish to add an object type -- say, "Lemma" -- to the list of object types that fancyref knows about, you may want to take a look at Enrico Gregorio's brilliant answer to the question "How to define a macro which declares a fancyref prefix? How to prevent it from outputting text?". Enrico provides a macro called \mkfancyprefix which lets users execute instructions such as \mkfancyprefix{lem}{Lemma}. This, in turns, lets users cross-reference lemmas (or is that lemmata?!) with an \fref{lem:...} instruction.

  • theoremref. As its name suggests, this package provides (fully dynamic) cross-references to theorems and related objects (lemmas, corollaries, etc.) Requires you to use the command \thlabel instead of \label to work. Functionality appears to be limited to theorem-like objects.

  • ntheorem. When loaded with the thref option, this package provides a very elegant method for creating fully-dynamic cross-references to theorem-like objects. It even works if some of the objects share the same counter variable -- as is often the case with theorems, lemmas, corollaries, and propositions. Main user command: \thref.

  • hyperref. In addition to providing its well-known capabilities for turning various cross-references -- both within a document and to objects outside the document -- into hyperlink targets, this package also provides the command \autoref. This command provides fully dynamic cross-references to a wide range of single instances of objects such as equations, sections, figures, tables, etc. A special aspect of this command is that the object's "name", e.g., "equation", is made a part of the hyperlink target, providing a large visual "target" for the mouse to click on and "jump" to the cross-referenced object.

    The "names" of the objects being cross-referenced with the \autoref command are, by default, in English. However, if the babel package is loaded with a suitable language option, hyperref will provide the objects' names in that language as well. As of mid-February 2020, available language options are (listed alphabetically) afrikaans, catalan, dutch, english (the default; synonyms: UKenglish, british, USenglish, and american), french (synonyms: frenchb, francais, acadian, and canadien), german (synonyms: ngerman, austrian, and naustrian), greek, italian, magyar (synonym: hungarian), portuges (synonyms: portuguese, brazil, and brazilan), russian, spanish, and vietnamese.

    In order for the hyperref package to work correctly, it is generally necessary to load it after all other packages that provide cross-referencing functions. The exception to this rule is the cleveref package -- see below.

  • The memoir document class: Provides commands \tref, \fref, \pref, etc to create dynamic cross-references to tables, figures, pages, etc. (Note that the memoir command \Cref, which is used to create cross-references to chapters, is incompatible with that of the cleveref package.) Use of these cross-referencing commands is great for the intelligibility of the LaTeX code. The obvious cost is a proliferation of cross-referencing commands. Wouldn't it be nice to have to remember only a very limited number of cross-referencing commands?!

  • cleveref. The current "king" of all cross-referencing packages. Main user commands: \cref and \crefrange (and the uppercase variants \Cref and \Crefrange for use at the start of a sentence).

    • In addition to doing lots of fancy behind-the-scenes footwork to create fully-dynamic cross-references, the \cref command can take not just one argument but many arguments. These arguments needn't be sorted by the author -- the package will do that for him/her! -- and they needn't even be of the same type, i.e., you can issue the command \cref{thm:this,lemma:that,prop:here,cor:there} and cleveref will automatically create a lexically correct group of cross-references for you.

    enter image description here

        \documentclass{article}
        \usepackage{amsthm}
        \usepackage[colorlinks]{hyperref}
        \usepackage[nameinlink]{cleveref}
        %% Define several theorem-like environments:
        \newtheorem{theorem}{Theorem}
        \newtheorem{lemma}[theorem]{Lemma}
        \newtheorem{proposition}[theorem]{Proposition}
        \newtheorem{cor}[theorem]{Corollary}
    
        \begin{document}
        %% Create a few dummy instances of the theorem-like environments:
        \begin{theorem}     \label{thm:this}   \end{theorem}
        \begin{lemma}       \label{lemma:that} \end{lemma}
        \begin{proposition} \label{prop:here}  \end{proposition}
        \begin{cor}         \label{cor:there}  \end{cor}
        \begin{proposition} \label{prop:where} \end{proposition}
        \begin{theorem}     \label{thm:what}   \end{theorem}
    
        \noindent % Now, use a single \cref command to cross-reference them.
        \Cref{thm:this,lemma:that,prop:here,cor:there,prop:where,thm:what}.
        \end{document}
    
    • If you have theorems, lemmas, corollaries, propositions, and other environments that share a common counter variable, the cleveref manual suggests that you load either the ntheorem or the amsthm package prior to defining these theorem-like environments (and also prior to loading cleveref, obviously). The ntheorem and amsthm packages provide some very handy auxiliary, behind-the-scenes information that helps cleveref figure out which name (theorem, lemma, corollary, etc) to associate with the object being cross-referenced, even if the environments share a common counter.

    • Extensive language adaptations. The document's language, if different from English, has to be specified as an option when the cleveref package is loaded. (cleveref is compatible with babel as well.) As of late-2016, the package can adapt the names of cross-referenced objects to the following 14 [!] languages: brazilian, catalan, danish, dutch, english (default), esperanto, french, german, italian, norwegian, russian, spanish, swedish, and ukrainian. Toby Cubitt (the author and maintainer of the cleveref package) actively welcomes submissions of object names for additional languages.

      An interesting tidbit of information regarding the rendering of the names of these objects: In English, there is no declension of nouns (including those used in cross-references), i.e., their form is the same whether the noun is used in the nominative, genitive, dative, accusative, etc form. This simplicity, however, does not apply to many other languages. :-( The cleveref package's singular and plural noun forms are all in the nominative form; if you use the package with a language other than English (or, I suppose, French, Spanish, and Italian), you should use the command \creflabel instead of \cref, and provide the appropriate case of the noun yourself, if the noun isn't being used in its nominative form. Even though you have to supply the name of the noun yourself when you use the \creflabel command, you still get to benefit from the sorting and compression facilities of the cleveref package.

    • Virtually all aspects of the cross-references can be customized fully.

    • The manual of the cleveref package recommends loading the ntheorem package with the thref option if you're going to create cross-references to theorem-like objects (especially if the objects share the same counter).

    • The cleveref package is fully compatible with other packages that provide cross-referencing commands -- including varioref, ntheorem, and hyperref -- as long as cleveref is loaded last.

    • Some caveats when using the cleveref package:

      1. The package is seriously incompatible with the showonlyrefs option of the mathtools package. By "seriously incompatible" I mean that if cleveref is loaded together with \usepackage[showonlyrefs]{mathtools}, not only will the \cref commands containing labels of equation objects be messed up, but many other cross-referencing packages will also experience major problems. Fortunately, this problem appears to be the only incompatibility between the cleveref and mathtools packages.
      2. If both the footmisc and the hyperref packages are loaded, there are some unresolved incompatibilities that affect cross-references to footnotes. This problem also affects a variety of other packages that provide cross-referencing functions, including cleveref.
      3. If your document loads the babel package with the option french, be sure not to use the : ("colon") character in the arguments of any \label and \cref-family instructions. This is because (a) the babel-french combination makes the : character "active" and (b) \cref needs to perform various operations on its argument; these operations will crash if the : character is active.

Addendum: Further cross-referencing possibilities

A major limitation of the cross-referencing mechanisms currently provided by the LaTeX kernel is that the \label command only writes two items to the .aux file: the value of the counter that was last incremented by a \refstepcounter or similar directive, and the number of the page on which this \label instruction is recorded. This limitation makes it impossible, for instance, to easily write something like "As was shown by Theorem~xx in Section~yy", as LaTeX doesn't provide a method for associating information about the theorem's number with the number of the section in which the theorem appears. The hyperref and cleveref packages apply some nifty hacks to the LaTeX kernel to overcome this limitation at least partially. However, these hacks aren't all that robust; this lack of robustness explains in part why these two packages should generally be loaded last.

The zref bundle of packages created by Heiko Oberdiek aims to overcome this limitation, by providing both an interface for macro programmers and several packages that make use of this interface. The package doesn't modify the basic \label, \ref, and \pageref commands. Instead, it provides the commands \zlabel and \zref, where \zlabel can be programmed to generate several rather than just two pieces of information to be written to the .aux file, and where options can be passed to \zref to specify which piece(s) of information should be cross-referenced.

To the best of my knowledge, so far none of the major cross-referencing packages (including hyperref) make use of the power afforded by the zref package. However, there are several smaller packages or "modules", also written by Heiko Oberdiek, that demonstrate some of the potential uses of the zref approach. For instance, the module abspage makes possible referencing the absolute page number of a document. This is useful for documents (including many books!) that have both roman-style and arabic-style page numbers: The macro \zref[abspage]{LastPage} references the total number of pages in the document, irrespective of the numbering styles that may be in use.