The cause for the possible page break is the \label
command that inserts a whatsit between the anchor and the box.
If I compile the following example
\documentclass{article}
\usepackage{hyperref}
\begin{document}
\hyperref[target]{My link}
\phantomsection\label{target}\nopagebreak% this stays on page 1
\vbox{bbb}
\showoutput
\end{document}
the relevant part of the log file is
....\pdfdest name{section*.1} xyz
....\penalty 10000
....\write1{\newlabel{target}{{}{\thepage }{}{section*.1}{}}}
....\penalty 10000
....\glue(\baselineskip) 3.11111
....\vbox(6.94444+0.0)x345.0
We see that an infinite penalty is added before the glue (that in your case will probably come from \lineskip
, but this is irrelevant), thus inhibiting this glue to be used as page break point.
If the \nopagebreak
is removed, we get
....\penalty 10000
....\write1{\newlabel{target}{{}{\thepage }{}{section*.1}{}}}
....\glue(\baselineskip) 3.11111
....\vbox(6.94444+0.0)x345.0
The whatsit (\write1
) is not a discardable item, so the glue can be used as a page break point.
So
\phantomsection\label{target}\nopagebreak
should do.
\clearpage
before\phantomsection