8

(Once upon a time I knew this stuff, just a few years ago, but now...)

How do I make node a and node b aligned with Text? Oh, and the rectangle should actuallybe filled and be "behind" the text.

\documentclass{article}

\usepackage{tikz} \usetikzlibrary{positioning}

\begin{document} Text \tikz{ \node[inner sep=0pt,outer xsep=0pt,outer ysep=3pt] (a) {node a}; \node[inner sep=0pt,outer xsep=0pt,outer ysep=3pt,right=of a] (b) {node b}; % other nodes \draw (a.south west) rectangle (b.north east); } \end{document}

I remember it's something about baseline or overlay...

I guess this will be duplicated to an existing question, but at the moment I can't even find the words to do a better search.

Enlico
  • 2,592
  • 1
    [anchor=base] will position a node. [baseline=(anchor)] will position an entire tikzpicture. [overlay, remember picture] is used mostly to align tikzpicture coordinates and \tikzmark. – John Kormylo Apr 28 '21 at 17:37
  • baseline=a.base to align with the base of a, then to align both nodes use anchor=base west and at (a.base west) on the second. – Andrew Stacey Apr 28 '21 at 18:12
  • @AndrewStacey, could you post an answer? Or maybe link to an existing one? – Enlico Apr 28 '21 at 19:07

3 Answers3

5

There are two things to consider when positioning nodes in line with external text. One is positioning the TikZ picture correctly with the text, the other is positioning the nodes correctly inside the picture. One can think of the first as the absolute position of the picture and the second as the relative position of the nodes within that picture.

The key concept here is that of the base anchor of a node. This is an anchor (or rather, set of anchors) that are vertically aligned with the baseline of the text of the node. This needs to be used both in positioning the picture in relation to the external text but also in positioning the nodes relative to each other.

To position the picture so that a particular node's baseline is on the text baseline, use the key baseline=(node.base) on the TikZ picture environment (or \tikz command).

To position individual nodes, ensure that the anchor is set to one of the base anchors, and that the position is in line with the base anchor of the node used to position it. A quick way to ensure that this happens is to use the positioning library and the base right=of <node> key (or left, of course).

Here's some code to demonstrate this. It also uses the hack from Pass options to the scope that is internally created by preaction to easily place nodes on layers and this, with the fit library, makes it easy to place a filled rectangle behind the placed nodes. I put all of them into the fit to ensure that all ascenders and descenders are taken into account. This isn't strictly necessary - first, last, tallest, deepest would be enough.

\documentclass[border=10pt]{standalone}
%\url{https://tex.stackexchange.com/q/594856/86}

\usepackage{tikz} \usetikzlibrary{positioning,fit}

\pgfdeclarelayer{back} \pgfdeclarelayer{front} \pgfsetlayers{back,main,front}

\makeatletter \pgfkeys{% /tikz/on layer/.code={ \pgfonlayer{#1}\begingroup \aftergroup\endpgfonlayer \aftergroup\endgroup }, /tikz/node on layer/.code={ \gdef\node@@on@layer{% \setbox\tikz@tempbox=\hbox\bgroup\pgfonlayer{#1}\unhbox\tikz@tempbox\endpgfonlayer\egroup} \aftergroup\node@on@layer }, }

\def\node@on@layer{\aftergroup\node@@on@layer}

\makeatother

\begin{document} Text before \tikz[baseline=(a.base)]{ \node[inner sep=0pt,outer xsep=0pt,outer ysep=3pt] (a) {node a}; \foreach[remember=\k as \pk (initially a)] \k in {b,c,p,q,A,M} { \node[inner sep=0pt,outer xsep=0pt,outer ysep=3pt,base right=of \pk] (\k) {node \k}; } \node[draw,fill=yellow,node on layer=back,fit={(a) (b) (c) (p) (q) (A) (M)}] {}; } Text afterwards \end{document}

Here's what that looks like:

nodes all aligned on a baseline

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
4

enter image description here

Use, as it was said in the comments, the baseline option for alignment, and layers to have the filled rectangle as background.

For the baseline=value, the value depends on the outer ysep value of the nodes.

The code

\documentclass[12pt, a5paper]{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\pgfdeclarelayer{background}
\pgfsetlayers{background, main}

\tikzset{ ab/.style={inner sep=0pt, outer xsep=0pt, outer ysep=3pt} }

\begin{document} \section*{Using baseline for figures and text alignment}

Text \begin{tikzpicture}[baseline=-4pt] \node[ab] (a) {node a}; \node[ab, right=of a] (b) {node b};

\begin{pgfonlayer}{background} \draw[fill=yellow] (a.south west) rectangle (b.north east); \end{pgfonlayer} \end{tikzpicture} and more text. \end{document}

Daniel N
  • 5,687
3

An alternative construction with tcolorbox

\documentclass{article}

\usepackage[most]{tcolorbox}

\newtcbox{mytcbox}[1][]{ on line, size=fbox, colback=yellow!30, sharp corners}

\begin{document} Text \mytcbox{node a\hspace{1cm}node p\hspace{5mm}node h} some more text \end{document}

enter image description here

Ignasi
  • 136,588