# TikZ: How to center captions below figures in matrix

I have three figures that I want to align in a matrix. Each figure is drawn in a different way and needs a caption that is centered below the corresponding figure.

Here is what I currently have: As you can see, the centering didn't go too well ;-)

The code that produces the above result is:

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

\begin{document}
\begin{tikzpicture}[grow=right]
\matrix[column sep=1cm] {
\node (R1)  {X};
\node (P1) [right=45pt of R1] {P};
\draw (R1) to (P1);
&
\node {A} child { node {P} } ;
&
\node {X}
child { node {R} }
child { node {R}
child { node {A} }
child { node {A}
child { node {P} }
child { node {P} }
child { node {P} }
}
child { node {A} }
}
child { node {R} }
;
\\
\node {caption}; & \node {other caption}; & \node {more caption};
\\
};
\end{tikzpicture}
\end{document}


How can I center the captions in a non-hacky way using TikZ?
I managed to get the result I need by adding absolute positioning to the labels, but that is a non-sustainable solution.

A) With three tikzpicture environments and without matrix

This way seems to work : three figures are aligned with the option baseline and captions are placed inside the code with (current bounding box.base)

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

\begin{document}

\begin{tikzpicture}[baseline]
\node (R1)  {X};
\node (P1) [right=45pt of R1] {P};
\draw (R1) to (P1);
\node[below=2cm] at (current bounding box.base) {caption 1};
\end{tikzpicture}
\hfill
\begin{tikzpicture}[grow=right,baseline]
\node {A} child { node {P} } ;
\node[below=2cm] at (current bounding box.base) {caption 2};
\end{tikzpicture}
\hfill
\begin{tikzpicture}[grow=right,baseline]
\node {X}
child { node {R} }
child { node {R}
child { node {A} }
child { node {A}
child { node {P} }
child { node {P} }
child { node {P} }
}
child { node {A} }
}
child { node {R} } ;
\node[below=2cm] at (current bounding box.base) {caption 3};
\end{tikzpicture}

\end{document} B) One tikzpicture environment with three scope environments and a matrix

We get the same result

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

\begin{document}
\begin{tikzpicture}
\matrix[column sep=2cm] {
\begin{scope}[baseline]
\node (R1)  {X};
\node (P1) [right=45pt of R1] {P};
\draw (R1) to (P1);
\node[below=2cm] at (current bounding box.base) {caption 1};
\end{scope}
&
\begin{scope}[grow=right,baseline]
\node {A} child { node {P} } ;
\node[below=2cm] at (current bounding box.base) {caption 2};
\end{scope}
&
\begin{scope}[grow=right,baseline]
\node {X}
child { node {R} }
child { node {R}
child { node {A} }
child { node {A}
child { node {P} }
child { node {P} }
child { node {P} }
}
child { node {A} }
}
child { node {R} } ;
\node[below=2cm] at (current bounding box.base) {caption 3};
\end{scope}
\\};
\end{tikzpicture}
\end{document}

• The use of scope is interesting. I tried to use it myself with the matrix solution to get the subfigures centered, but I couldn't find out how. The (current bounding box.base) is an interesting trick. – Ruben Verborgh Mar 27 '13 at 8:06
• @RubenVerborgh Not exactly a trick it's a feature. baseline is also interesting to know. You need to know how to place objects with Tikz without the use of raw coordinates. Tikz gives you anchors for the nodes, the bounding box, the page etc. I actually work about notes on Tikz and it's a big part of the notes. – Alain Matthes Mar 27 '13 at 8:24

One possibility would be to name some appropriate nodes in each cell of the first row, then use the fit library to build some framing nodes and finally place the captions with respect to these new nodes:

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

\begin{document}
\begin{tikzpicture}[grow=right]
\matrix[column sep=1cm] {
\node (R1)  {X};
\node (P1) [right=45pt of R1] {P};
\draw (R1) to (P1);
\node[inner sep=0pt,fit= (R1) (P1)]  (box1) {}; &
\node (root) {A} child { node (child) {P} } ;
\node[inner sep=0pt,fit= (root) (child)]  (box2) {};
&
\node (lroot) {X}
child { node {R} }
child { node {R}
child { node {A} }
child { node {A}
child { node {P} }
child { node (lchild) {P} }
child { node {P} }
}
child { node {A} }
}
child { node {R} }
;
\node[inner sep=0pt,fit= (lroot) (lchild)]  (box3) {};
\\
\node[below=of box1.center] {caption}; & \node[below=of box2.center] {other caption}; & \node[below=of box3.center] {more caption};
\\
};
\end{tikzpicture}
\end{document} • I see, great suggestion. Would there be any way to do this without manually assigning center nodes, i.e., saying to TikZ "the center of this subpicture"? – Ruben Verborgh Mar 26 '13 at 22:14

It seems to me that your tikzpictures can actually be separated since there's no co-dependence between them. As such, I would use the subcaption package's subfigure environment as follows. The idea is one that I have used quite a few times before:

• measure the biggest picture
• then use its height to justify the smaller pictures vertically.

Here's the complete MWE:

% arara: pdflatex
% !arara: indent: {overwrite: true}
\documentclass{article}
\usepackage{geometry}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage{subcaption}
\newsavebox{\tempbox}

\begin{document}

% store the biggest picture
% so that we can measure it
\sbox{\tempbox}{%
\begin{tikzpicture}[grow=right]
\node {X}
child { node {R} }
child { node {R}
child { node {A} }
child { node {A}
child { node {P} }
child { node {P} }
child { node {P} }
}
child { node {A} }
}
child { node {R} };
\end{tikzpicture}%
}

\begin{figure}[!htb]
\centering
\begin{subfigure}{.33\textwidth}
\centering
\vbox to\ht\tempbox{%
\vfill
\begin{tikzpicture}[grow=right]
\node (R1)  {X};
\node (P1) [right=45pt of R1] {P};
\draw (R1) to (P1);
\end{tikzpicture}
\vfill
}
\caption{caption}
\end{subfigure}%
\begin{subfigure}{.33\textwidth}
\centering
\vbox to\ht\tempbox{%
\vfill
\begin{tikzpicture}[grow=right]
\node {A} child { node {P} } ;
\end{tikzpicture}
\vfill
}
\caption{other caption}
\end{subfigure}%
\begin{subfigure}{.33\textwidth}
\centering
% use the save box
\usebox{\tempbox}
\caption{more caption}
\end{subfigure}
\end{figure}
\end{document}

• This is a valid solution and easier from a LaTeX perspective. The only downside seems that you indeed have to measure the largest figure beforehand. However, for this question, I'm specifically interested in a TikZ solution. I will clarify that in the question. – Ruben Verborgh Mar 27 '13 at 8:09
• @RubenVerborgh fair enough :) In my mind, as soon as you say caption I automatically want to label and ref it though- this is easy with my solution, much harder with the others :) – cmhughes Mar 27 '13 at 14:41
{"ft_lang_label":"__label__en","ft_lang_prob":0.66453606,"math_prob":0.7543546,"size":1016,"snap":"2020-10-2020-16","text_gpt3_token_len":313,"char_repetition_ratio":0.19268775,"word_repetition_ratio":0.13407822,"special_character_ratio":0.31889763,"punctuation_ratio":0.097826086,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9976576,"pos_list":[0,1,2,3,4,5,6,7,8],"im_url_duplicate_count":[null,2,null,2,null,2,null,2,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2020-02-18T01:16:24Z\",\"WARC-Record-ID\":\"<urn:uuid:0060c9de-9315-4a35-b74f-b458602ad0d0>\",\"Content-Length\":\"164240\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:ebd28fb8-7024-491a-8123-7cb389466a6a>\",\"WARC-Concurrent-To\":\"<urn:uuid:3f7daa40-8b9d-4c6e-b392-d6760320edbe>\",\"WARC-IP-Address\":\"151.101.1.69\",\"WARC-Target-URI\":\"https://tex.stackexchange.com/questions/104457/tikz-how-to-center-captions-below-figures-in-matrix\",\"WARC-Payload-Digest\":\"sha1:6BE6SSFMAHWWEBRUR5UB3M5HXXNI5F47\",\"WARC-Block-Digest\":\"sha1:PU4R2NIXRN3RJ7IJSEW554OPYBFYV62K\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2020/CC-MAIN-2020-10/CC-MAIN-2020-10_segments_1581875143455.25_warc_CC-MAIN-20200217235417-20200218025417-00471.warc.gz\"}"}