Referencing to "above" or "below"?

varioref can in fact do this you just need to give its \vpageref command a hint what to write to refer to an element on the same page. From the documentation:

But in fact \vpageref allows even more control. If has two optional arguments. With the first one, one can specify the text that should be used if label and reference fall on the same page. This is very helpful if both are near to each other, so that they may or may not be separated by a page break. In such a case we usually know (!) whether the reference is before or after the label so that we can say something like ... see the example \vpageref[above]{ex:foo} which shows ... which will then come out as “. . . see the example above which shows . . . ”

The point is that if there is a page break in between the label and the element, \vpageref will notice this and insert something like on the previous page instead.


You can also implement the labels yourself by having labels define a flag and references check the flag existence. Some additional bookkeeping is needed to warn about undefined labels.

\documentclass{article}

\makeatletter
\newcount\here@undef
\newcommand{\here}[1]{%
  \@ifundefined{here@#1@undef}{}{\advance\here@undef by -1}%
  \@namedef{here@#1}{}}
\newcommand{\where}[1]{%
  \@ifundefined{here@#1}{%
    below%
    \@ifundefined{here@#1@undef}{%
      \@namedef{here@#1@undef}{}%
      \advance\here@undef by 1
    }{}%
  }{%
    above%
  }%
}
\AtEndDocument{%
  \ifnum\here@undef>0
    \GenericWarning{}{There were undefined above/below labels}%
  \fi}
\makeatother

\begin{document}

As mentioned \where{test}, $2+2=4$.

We state that $2+2=4$.\here{test}

As mentioned \where{test}, $2+2=4$.

\end{document}

Result


You can check the y-coordinate of a mark on a page and perform a comparison to decide whether you should print above or below. zref's savepos module can help with that:

enter image description here

\documentclass{article}

\usepackage{zref-savepos}

\newcounter{whereq}
\newcommand{\location}[1]{\zsaveposy{#1}}
\newcommand{\where}[1]{%
  \stepcounter{whereq}% New "where" request
  \location{whereq-\thewhereq}% Mark location
  % Test location based on y-coordinate
  \ifdim\zposy{whereq-\thewhereq}sp<\zposy{#1}sp
    above%
  \else
    below%
  \fi}

\begin{document}

As mentioned \where{test}, $2+2=4$.

We state that $2+2=4$.\location{test}

As mentioned \where{test}, $2+2=4$.

\end{document}

Of course, the above doesn't really care what page you perform the \location and \where macros on. However, it could be extended to condition on the page number as well.