5

Consider the following minimal example where I want to draw a rectangle behind a sequence of numbers (to highlight them):

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{backgrounds,calc}

\NewDocumentCommand{\tikzmark}{ m }{\tikz[overlay, remember picture] \node (#1) {};}

\newcounter{seq}
\NewDocumentCommand{\seqstart}{}{%
  \stepcounter{seq}% Start a new sequence
  \tikzmark{seq-start-\theseq}}% Set start marker
\NewDocumentCommand{\seqend}{}{%
  \tikzmark{seq-end-\theseq}% Set end marker
  \tikz[remember picture, overlay]
    \scoped [on background layer]
      \fill [fill=blue!10!white] ($(seq-start-\theseq.south west) + (-0.5pt,1pt)$) rectangle ($(seq-end-\theseq.south east) + (0.5pt,1.1\normalbaselineskip)$);%
}

\begin{document}

\[
  12, 15, 8, 11, 4, 7, 0, 3, 16, 19, 12, 15, 8, 11, 4, 7, 0, 3, \ldots
\]

\[
  \seqstart{}12, 15, 8, 11, 4, 7, 0, 3, 16, 19\seqend{}, 12, 15, 8, 11, 4, 7, 0, 3, \ldots
\]

\end{document}

The idea is that \seqstart would set a (counter-driven) \tikzmark representing the start of the sequence to be marked. Then \seqend would set a \tikzmark at the end and highlight it using the background layer. The counter allows for multiple such sequence marking within a larger document.

However, the output shows that the rectangle highlighting a part of the sequence is not being drawn on background layer as requested.

enter image description here

Why is that? How can I ensure the rectangle is drawn on the background layer behind document/text elements?

The backgrounds library documentation (in the tikz documentation, section 45) mentions that on background layer can only be used inside a {scope} or \scoped, which is done above.

8
  • 2
    To my knowledge, tikzmark makes a tikzpicture which is overlain on the page. The background layer is a layer of that tikzpicture, which is drawn after the glyphs. I don't think that it means the literal background of the document, but rather a layer of the tikzpicture. Very interesting question though, I certainly haven't been able to figure out how to achieve the desired effect. +1 Commented Feb 21 at 7:30
  • 3
    why tikz a must? lua-ul maybe better choice for highlight. Commented Feb 21 at 8:39
  • 1
    Jasper is right about the background layer not being the background of the page. In recent versions of tikzmark I've revisited highlighting text using the tikzmark mechanism. Take a look at the documentation. I think it's in the ctan version. Commented Feb 21 at 9:13
  • 1
    Looking at this post tex.stackexchange.com/questions/668244/…, by replacing on background layer with blend mode=multiply Commented Feb 21 at 11:38
  • 1
    Also, TikZ layers simply control the order in which the layers are drawn. Commented Feb 21 at 14:47

4 Answers 4

5

Since TikZ's background layer is specific to the (tikz)picture it is used in, writing on background layer doesn't work as expected. The most convenient way to access the (absolute) background for writing content behind text is to add it to the shipout/background hook.

enter image description here

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{backgrounds,calc}

\NewDocumentCommand{\tikzmark}{ m }{\tikz[overlay, remember picture] \node (#1) {};}

\newcounter{seq}
\NewDocumentCommand{\seqstart}{}{%
  \stepcounter{seq}% Start a new sequence
  \tikzmark{seq-start-\theseq}}% Set start marker
\NewDocumentCommand{\seqend}{}{%
  \tikzmark{seq-end-\theseq}% Set end marker
  \AddToHook{shipout/background}{% Add fill to absolute background layer
    \tikz[remember picture, overlay]
      \fill [fill = blue!10!white] ($(seq-start-\theseq.south west) + (-0.5pt,1pt)$) rectangle ($(seq-end-\theseq.south east) + (0.5pt,1.1\normalbaselineskip)$);%
  }%
}

\begin{document}

\[
  12, 15, 8, 11, 4, 7, 0, 3, 16, 19, 12, 15, 8, 11, 4, 7, 0, 3, \ldots
\]

\[
  \seqstart{}12, 15, 8, 11, 4, 7, 0, 3, 16, 19\seqend{}, 12, 15, 8, 11, 4, 7, 0, 3, \ldots
\]

\end{document}
2
  • This is a really cool technique to slip in a tikzpicture early on in the documents development. Commented Feb 22 at 7:27
  • 1
    This is the idea behind tikzmark's highlighting technique Commented Feb 22 at 16:32
4

The tikzmark library already has this capability. It uses the technique you note in your answer of using the shipout hooks to insert a layer under the text (or over the text, the option is yours). There are, of course, lots of styling options for the highlighting. It also handles page breaks.

% Source - https://tex.stackexchange.com/q/760005
% Posted by Werner
% Retrieved 2026-02-22, License - CC BY-SA 4.0

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{backgrounds,calc,tikzmark}
\usetikzmarklibrary{highlighting}

\begin{document}

\[
  12, 15, 8, 11, 4, 7, 0, 3, 16, 19, 12, 15, 8, 11, 4, 7, 0, 3, \ldots
\]

\[
  \StartHighlighting 12, 15, 8, 11, 4, 7, 0, 3, 16, 19\StopHighlighting, 12, 15, 8, 11, 4, 7, 0, 3, \ldots
\]

\end{document}

The result of the above code, where a part of a sequence is highlighted

4

Here's an extension of Andrew Stacey's answer which tries to reproduce your output, using

,fill      = blue!10!white
,sharp corners
,highlighter/.cd
,depth     = 0.3\normalbaselineskip
,height    = 0.8\normalbaselineskip
,offset    = 3.5pt
,direction = box

Example:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{tikzmark}
\usetikzmarklibrary{highlighting}

\begin{document}

\[
  12, 15, 8, 11, 4, 7, 0, 3, 16, 19, 12, 15, 8, 11, 4, 7, 0, 3, \ldots
\]

\[
  \StartHighlighting[
    ,fill      = blue!10!white
    ,sharp corners
    ,highlighter/.cd
    ,depth     = 0.3\normalbaselineskip
    ,height    = 0.8\normalbaselineskip
    ,offset    = 3.5pt
    ,direction = box
  ] 12, 15, 8, 11, 4, 7, 0, 3, 16, 19\StopHighlighting{}, 12, 15, 8, 11, 4, 7, 0, 3, \ldots
\]

\tikzset{
  ,every highlight path/.style = {
    ,fill      = blue!10!white
    ,sharp corners
  }
  ,highlighter/.cd
  ,depth     = 0.3\normalbaselineskip
  ,height    = 0.8\normalbaselineskip
  ,offset    = 3.5pt
  ,direction = box
}

\[
  \StartHighlighting{} 12, 15, 8, 11, 4, 7, 0, 3, 16, 19\StopHighlighting{}, 12, 15, 8, 11, 4, 7, 0, 3, \ldots
\]

\end{document}

Example

2

I thought of this approach:

\documentclass{article}

\usepackage{tikz}

\newcommand{\blah}[1]{%
    \begin{tikzpicture}[baseline=(current bounding box.south)]
        \node[
            rectangle
            ,fill=none
            ,draw=none
            ,semithick
            ,inner sep=0pt
        ] at (0,0) {#1};
        \begin{scope}
            \pgflowlevelsynccm
            \node[
            rectangle
            ,fill=gray!40
            ,draw=none
            ,semithick
            ,inner sep=2pt
        ] at (0,0) {#1};
        \end{scope}
    \end{tikzpicture}
}

\begin{document}

Blah blah blah; \blah{blah blah blah} blah blah.

\end{document}

output

3
  • Will it work for longer texts, with line break, with page break? Commented Feb 21 at 8:15
  • 1
    @MS-SPO No, that dounds very complicated to implement in tikz. Let me think about it. Commented Feb 21 at 9:06
  • No problem. I suggest to wait for the OP to further clarify the requirements. I.e. for short enough texts your solution should be fine (enough). Commented Feb 21 at 10:42

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.