# Method for aligning nodes of different sizes at specified sections

I'm trying to make a tikz diagram in which I can place nodes with long pieces of text, one above the other, such that I can specify sections which are to be centered (things outside these sections are then dragged along) with a vertical arrow connecting the centers of the centered sections.

That's kind of a jumble of words, so to give an example, I'd like something like this:

\begin{tikzpicture}
\node (a) at (0,1) {really long stuff \centerthis{blahh} other stuff};
\node (b) at (0,0) {more stuff \centerthis{blah blah blah} possibly other stuff};
\draw[->] (a) -- (b);
\end{tikzpicture}


to automatically produce this:

            really long stuff (blahh) other stuff
|
|
v
more stuff (blah blah blah) possibly other stuff


so that the center of (blahh) is at (0,1) and the center of (blah blah blah) is at (0,0).

The main things I'm looking for in a solution are that

• I want to avoid any manual adjustment of distances or sizes.
• I want everything to appear on the same baseline. For example, I tried making 6 nodes, for upper and lower left, middle, and right, and when one of them had a descender and the others did not, it looked off. Perhaps there's a way around this?

Apologies for not having more to offer, but I'm simply stuck on this. Of course, the hypothetical code I used above is just an idea, if you see another way of setting up a solution (as I'm sure there are many), please post it as well.

-

If you can get away with 6 nodes with (almost) proper alignment

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}[every node/.style={outer sep=0,inner sep=0,text depth=0.3ex},
node distance=0.3em]
\node (a) at (0,1) {Blaaaahh};
\node[left=of a.west] {really long stuff};
\node[right=of a.east] {other stuff};

\node[below= 1 cmof a] (b) {blah blah blah};
\node[left=of b.west] {asymmetric};
\node[right=of b.east] {lipsum stuff};
\draw[-latex] (a) -- (b);
\end{tikzpicture}
\end{document}


Oherwise, probably a \tikzmark answer is on its way.

-

# Solution “Complicated”

This solution calculates the amount of xshift that both nodes have to be moved so that the middle of the to-centered part lays on the at (x,y) point.
These xshift amounts are then again used for the arrow that is to be drawn.

This solution uses the calc packacke.

This solution provides:

• Style CenterLCRa/b that takes three arguments:
1. the left part of the text,
2. the center part of the text (which is only used for the definition of \LCR, see below) and
3. the right part of the text.
• Macro \LCR that is set after the style CenterLCRa/b is used. It simply contains the node's text so that it doesn't have to be typed again.
• Path style LCR that draws the line between the (new) centers.
• Internally: Lengths \WidthOfLeft, \WidthOfRight and \xShiftA/B, macros \tikzCenterLCRa/b and TikZ styes centerLCRa/b

## Code

\documentclass[tikz,border=2pt]{standalone}
\usepackage{tikz,calc}
\newlength{\WidthOfLeft}
\newlength{\WidthOfRight}
\newlength{\xShiftA}
\newlength{\xShiftB}

\newcommand{\tikzCenterLCRa}[3]{% #1 = L, #2 = C, #3 = R
\setlength{\WidthOfLeft}{\widthof{#1}}%
\setlength{\WidthOfRight}{\widthof{#3}}%
\setlength{\xShiftA}{-.5\WidthOfLeft+.5\WidthOfRight}
\global\xShiftA=\xShiftA\relax%
\def\LCR{#1#2#3}
}
\newcommand{\tikzCenterLCRb}[3]{% #1 = L, #2 = C, #3 = R
\setlength{\WidthOfLeft}{\widthof{#1}}%
\setlength{\WidthOfRight}{\widthof{#3}}%
\setlength{\xShiftB}{-.5\WidthOfLeft+.5\WidthOfRight}
\global\xShiftB=\xShiftB\relax
\def\LCR{#1#2#3}
}
\tikzset{
centerLCRa/.code n args={3}{\tikzCenterLCRa{#1}{#2}{#3}},
CenterLCRa/.style n args={3}{
centerLCRa={#1}{#2}{#3},
xshift=\the\xShiftA
},
centerLCRb/.code n args={3}{\tikzCenterLCRb{#1}{#2}{#3}},
CenterLCRb/.style n args={3}{
centerLCRb={#1}{#2}{#3},
xshift=\the\xShiftB
},
LCR/.style={
to path={
([xshift=-\the\xShiftA]\tikztostart) -- ([xshift=-\the\xShiftB]\tikztotarget) \tikztonodes
}
}
}

\begin{document}
\begin{tikzpicture}[every node/.style=draw]
\node[CenterLCRa={really long stuff }{xxx}{ other stuff}]             (a) at (0,1) {\LCR};
\node[CenterLCRb={more stuff }{blah xxx blah}{ possibly other stuff}] (b) at (0,0) {\LCR};
\draw[->] (a.south) to[LCR] (b.north);
\end{tikzpicture}
\end{document}


# Solution “Dirty”

## Nodes bigger than their content

This solution has the disadvantage of using boxes that are bigger than their content, so that the final node will be wider than usual (bounding box, drawing mechanism).

### Code

\documentclass[tikz,border=2pt]{standalone}
\usepackage{calc}
\newlength{\WidthOfLeft}
\newlength{\WidthOfRight}
\newcommand{\centerLCR}[3]{%
\settowidth{\WidthOfLeft}{#1}%
\settowidth{\WidthOfRight}{#3}%
\ifdim\WidthOfLeft<\WidthOfRight\relax%
\setlength{\WidthOfLeft}{\WidthOfRight}%
\fi%
\makebox[\WidthOfLeft][r]{#1}#2\makebox[\WidthOfLeft][l]{#3}%
}
\begin{document}
\begin{tikzpicture}
\node (a) at (0,1) {\centerLCR{really long stuff }{blahh}{ other stuff}};
\node (b) at (0,0) {\centerLCR{more stuff }{blah blah blah}{ possibly other stuff}};
\draw[->] (a) -- (b);
\end{tikzpicture}
\begin{tikzpicture}[every node/.style=draw]
\node (a) at (0,1) {\centerLCR{really long stuff }{blahh}{ other stuff}};
\node (b) at (0,0) {\centerLCR{more stuff }{blah blah blah}{ possibly other stuff}};
\draw[->] (a) -- (b);
\end{tikzpicture}
\end{document}


## Nodes smaller than their content

If the boxes use rather the smaller width, i.e.

\ifdim\WidthOfLeft>\WidthOfRight\relax% > instead of <


then the bounding box is even worse. (See cut-off "her stuff" in output.)
This won't be a problem if there's more around these nodes.

-