3

The following code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{tikzmark}
\begin{document}
This is some text: \tikzmarknode{Foo}{foo}.

And this is some text in between that the filling partially covers

And this is another node:\tikzmarknode{Bar}{bar}
\begin{tikzpicture}[remember picture, overlay]
  \draw[draw=none, fill=red] (Foo.north west)
    -- (Bar.south west)
    -- (Bar.south east)
    -- (Foo.north east)
    -- cycle;
\end{tikzpicture}
\end{document}

generates this output enter image description here

Even if I lower the filling opacity, the colored layer will still be above text.

How can I have it below the text?

3
  • 2
    Try to change the blend mode, see e.g. tex.stackexchange.com/a/684757/36296 In your case \begin{tikzpicture}[remember picture, overlay,blend mode=multiply] should do the job May 14, 2023 at 19:02
  • The only way to put the tikzpicture in the background is to draw it first. Interestingly, you can do that with (pic cs:Foo) and (pic cs:Bar), but only using \tikzmark instead of \tikzmarknode. May 14, 2023 at 21:40
  • @JohnKormylo actually, the tikzmark library can save node information to the aux file which makes it possible to use a node's position before it is defined, but it doesn't do it by default for \tikzmarknode so you'd have to add the right keys. May 14, 2023 at 22:32

3 Answers 3

3

This shows how to do it using a plain old tikzmark.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{tikzmark}
\begin{document}

\begin{tikzpicture}[remember picture, overlay]
  \draw[draw=red, thick] (pic cs:Foo) -- (pic cs:Bar);
\end{tikzpicture}%
This is some text: \tikzmark{Foo}

And this is some text in between that the filling partially covers

And this is another node:\tikzmark{Bar}

\end{document}

This shows how to do it with a savebox. The coordinates (relative to the origins) are saved globally, although the \pgfsyspdfmark doesn't get written to the aux file until the savebox is used. It will take two runs anyway.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{tikzmark}

\newsavebox{\tempbox}

\begin{document}

\savebox{\tempbox}{\begin{minipage}{\textwidth}
This is some text: \tikzmarknode{Foo}{foo}.

And this is some text in between that the filling partially covers

And this is another node:\tikzmarknode{Bar}{bar}
\end{minipage}}%

\noindent\begin{tikzpicture}[remember picture, overlay]
  \draw[draw=none, fill=red] (Foo.north west)
    -- (Bar.south west)
    -- (Bar.south east)
    -- (Foo.north east)
    -- cycle;
\end{tikzpicture}\usebox\tempbox
\end{document}
2

Only the position of the whole TikZ picture is saved to the aux files, the dimensions of nodes are only known after they have been constructed.

Here's an approach where the TikZ picture is constructed only after all nodes have been constructed (and are then known). By adding this TikZ picture to the background shipout hook this will be placed behind the normal text.

Code (shipout)

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{tikzmark}
\NewDocumentEnvironment{tikz-bg}{O{} +b}{%
  \AddToHookNext{shipout/background}{%
    \put(0,0){%
      \begin{tikzpicture}[remember picture,overlay,#1]%
        #2%
      \end{tikzpicture}}}}{}
\begin{document}

This is some text: \tikzmarknode{Foo}{foo}.

And this is some text in between that the filling partially covers

And this is another node:\tikzmarknode{Bar}{bar}
\begin{tikz-bg}
\fill[red] (Foo.north west) -- (Bar.south west)
        -- (Bar.south east) -- (Foo.north east) -- cycle;
\end{tikz-bg}
\end{document}

The tikzmark library has support for saving the node (i.e. its placement inside a TikZ picture and its anchors):

Each node that needs to be known beforehand needs to use save node whereas the nodes TikZ picture needs save nodes to file.

For some reason, everything is shifted downwards, maybe something's not saved correctly or at the corrent point. The commented hack seems to be a workaround for the underlying issue.

Code (saved nodes)

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{tikzmark}
\tikzset{
  every tikzmarknode picture/.style=save nodes to file,
  restore nodes from file,
  save node/.append style={anchor=center}% hack
}
\begin{document}
\tikz[remember picture, overlay]
  \fill[red] (Foo.north west) -- (Bar.south west)
          -- (Bar.south east) -- (Foo.north east) -- cycle;%
This is some text: \tikzmarknode[save node]{Foo}{foo}.

And this is some text in between that the filling partially covers

And this is another node: \tikzmarknode[save node]{Bar}{bar}
\end{document}
1
  • every tikzmarknode/.style=save node to save all nodes without having to use save node individually. May 14, 2023 at 23:12
2

Here is a simple solution using blend mode=mutliply as suggested in a comment by samcarter_is_at_topanswers.xyz. This works well when overlaying an image with black text, as the product of black (color=0) and any other color is still black.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{tikzmark}
\begin{document}
This is some text: \tikzmarknode{Foo}{foo}.

And this is some text in between that the filling partially covers

And this is another node:\tikzmarknode{Bar}{bar}
\begin{tikzpicture}[remember picture, overlay, blend mode=multiply]
  \draw[draw=none, fill=red] (Foo.north west)
    -- (Bar.south west)
    -- (Bar.south east)
    -- (Foo.north east)
    -- cycle;
\end{tikzpicture}
\end{document}

And here is the resulting output

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .