8

Question

I want to place two TikZ pictures side by side:

Two paragraphs with TikZ pictures between them. The captions are aligned. There is equal space between and to either side of the TikZ pictures. They are vertically centered. The first picture is tall and the second is wider than half the page.

Note:

  • They are vertically centered.
  • One is wider than half the page.
  • The three gaps are equal (as if by using \hfil <a> \hfil <b> \hfil).
  • The captions are vertically aligned.

Long captions should also be handled correctly (i.e. they should wrap, just like they normally do).

The solution should avoid trial-and-error lengths such as \begin{minipage}{5.95cm}, \begin{minipage}{0.3\textwidth} and \qquad.



What I've tried

I've looked at about two dozen questions here but none of the answers were satisfactory. This section is an attempt to summarize them and address their flaws.

Assume the following preamble:

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tikz}
\usepackage{caption}
\usepackage{subfig}
\usepackage{floatrow}
\usepackage{tabularx}

\newcommand\rectangle[2]{%
    \begin{tikzpicture}[baseline=(current bounding box.center)]
        \draw(0,0) rectangle(#1, #2);
    \end{tikzpicture}%
}

minipage

\vspace{0.5cm}
\noindent
\begin{minipage}{5.95cm} % (1)
    \centering
    \rectangle{4}{8}
    \captionsetup{type=figure}
    \caption{A tall boi.}
\end{minipage}
\begin{minipage}{8cm}
    \rectangle{8}{4}
    \captionsetup{type=figure}
    \caption{A wide boi.} % (2)
\end{minipage}
\vspace{0.5cm} % (3)

Problems

  1. The minipage widths are determined through trial and error.
  2. The captions aren't vertically aligned.
  3. I don't know how much vspace to use. If I don't use any, there is no vertical space between the figures and the paragraphs.

subfloat

\begin{figure}[H]
    \centering
    \subfloat[\centering A tall boi.]{% (1)
        \rectangle{4}{8}
    }%
    \qquad% (2)
    \subfloat[\centering A wide boi.]{% (3)
        \rectangle{8}{4}
    }
\end{figure}

Problems

  1. The captions are a different style and have different numbering.
  2. The spacing between the figures is determined through trial and error.
  3. The captions aren't vertically aligned.

floatrow

\begin{figure}[H]
    \centering
    \begin{floatrow}
        \ffigbox[\FBwidth]{\caption{A tall boi.}}{%
            \rectangle{4}{8}
        }% (1)
        \ffigbox[\FBwidth]{\caption{A wide boi.}}{%
            \rectangle{8}{4} % (2)
        }%
    \end{floatrow}
\end{figure}

Problems

  1. The spacing is wrong.
  2. The figures aren't vertically centered.

tabularx

\vspace{0.5cm} % (1)
\noindent
\begin{tabularx}{\textwidth}{XX} % (2)
    \rectangle{4}{8} &
    \rectangle{8}{4} \\
    \captionsetup{type=figure}
    \caption{A tall boi.} &
    \captionsetup{type=figure}
    \caption{A wide boi.}
\end{tabularx}

Problems

  1. \vspace again.
  2. Both columns are equally wide (wide enough to fit the second figure).

This is the best one so far



Minimal working example

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tikz}
\usepackage{lipsum}

\newcommand\rectangle[2]{%
    \begin{tikzpicture}[baseline=(current bounding box.center)]
        \draw(0,0) rectangle(#1, #2);
    \end{tikzpicture}%
}

\begin{document}

\lipsum[1][1-3]

\noindent\hfil
\rectangle{4}{8}
\hfil
\rectangle{8}{4}
\hfil

\lipsum[2][1-3]

\end{document}

3 Answers 3

5

This uses a combination of saveboxes and \parboxes. The captions are placed in \parboxes to control the width (minipages will do just as well). The \nulls prevent \abovecaptionskip from geing ignored.

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tikz}
\usepackage{lipsum}
\usepackage{caption}

\newcommand\rectangle[2]{%
    \begin{tikzpicture}[baseline=(current bounding box.center)]
        \draw(0,0) rectangle(#1, #2);
    \end{tikzpicture}%
}

\begin{document}

\lipsum[1][1-3]

\begin{figure}[ht]
\sbox0{\rectangle{4}{8}}% measure width
\sbox1{\rectangle{8}{4}}%
\centering
\usebox0\hfil\usebox1\par
\parbox[t]{\wd0}{\null
    \caption{A tall boi.}}\hfil
\parbox[t]{\wd1}{\null
    \caption{A wide boi.}}
\end{figure}

\lipsum[2][1-3]

\end{document}
0
2

As starting point:

  • use tabularray package
  • calculate table column separator(s). In your case by
(\linewidth-<width of first image>-<width of second image>)/6

where 6 is number of column separators in table.

In the cases, when width of images is know in advance, than MWE in your particular case can be:

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tikz}
\usepackage{lipsum}

\usepackage{tabularray}
\UseTblrLibrary{counter}
\newcommand\rectangle[2]{%
    \begin{tikzpicture}[baseline=(current bounding box.center)]
        \draw(0,0) rectangle(#1, #2);
    \end{tikzpicture}%
}

\begin{document}
\lipsum[1][1-3]
    \begin{figure}[ht]
    \centering
\begin{tblr}{colsep = {(\linewidth-8cm-4cm)/6},
             colspec = {Q[m, wd=4cm] Q[m, wd=8cm]},
             row{2}  = {h},
             }
\rectangle{4}{8}
    &
\rectangle{8}{4}    \\
\caption{figure 1}
    &   \caption{figure 2}
\end{tblr}
    \end{figure}
   
\lipsum[2][1-3] 
\end{document}

enter image description here

Edit:
However, when the width of images is unknown in advance, you need to measure their width similarly as @John Kormylo do in his answer and inset those width in width of columns and use in calculation of colsep as is indicated at beginning of answer:

\usepackage[showframe]{geometry}
\usepackage{tikz}
\usepackage[skip=1ex]{caption}
\usepackage{lipsum}

\usepackage{tabularray}
\UseTblrLibrary{counter}
\newcommand\rectangle[2]{%
    \begin{tikzpicture}[baseline=(current bounding box.center)]
        \draw(0,0) rectangle(#1, #2);
    \end{tikzpicture}%
}

\begin{document}
\lipsum[1][1-3]
    \begin{figure}[ht]
    \centering
\sbox0{\rectangle{4}{8}}% measure of the first image width
\sbox1{\rectangle{8}{4}}% measure of the second image width
\begin{tblr}{colsep = {(\linewidth-\wd0-\wd01)/6},
             colspec = {Q[m, wd=\wd0] Q[m, wd=\wd1]},
             row{2}  = {h},
             rowsep  = 0pt
             }
\rectangle{4}{8}
    &
\rectangle{8}{4}    \\
\caption{figure 1}
    &   \caption{figure 2}
\end{tblr}
    \end{figure}
   
\lipsum[2][1-3] 
\end{document}

Result is the same as before.

2
  • Thanks for your effort! Unfortunately this seems to rely on the specific dimensions of the example figures (colsep = {(\linewidth-8cm-4cm)/6}, colspec = {Q[m, wd=4cm] Q[m, wd=8cm]}). Let me know if I misinterpreted that part
    – glibg10b
    Commented Jul 19, 2023 at 13:52
  • 1
    @glibg10b, in your particular case you are right, but in original answer is indicated how you should do in general, when width is unknown in advance. This case is now spelled out in added new example.
    – Zarko
    Commented Jul 19, 2023 at 18:13
0

This answer extends John's answer:

Before After
before after
\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tikz}
\usepackage{lipsum}
\usepackage{caption}
\usepackage{calc}

\newcommand\rectangle[2]{%
    \begin{tikzpicture}[baseline=(current bounding box.center)]
        \draw(0,0) rectangle(#1, #2);
    \end{tikzpicture}%
}

\begin{document}

\lipsum[1][1-3]

\begin{figure}[ht]
\sbox0{\rectangle{3}{6}}%
\sbox1{\rectangle{6}{3}}%
\centering
\usebox0\hfil\usebox1\par
\parbox[t]{\wd0+(\textwidth-\wd0-\wd1)/3-6pt}{\null% (2)
    \caption{\lipsum[1][4-6]}}%
\hspace{6pt}% (1)
\parbox[t]{\wd1+(\textwidth-\wd0-\wd1)/3-6pt}{\null% (2)
    \caption{\lipsum[1][7-9]}}%
\end{figure}

\lipsum[2][1-3]

\end{document}
  1. The caption \parboxes have a 6pt gap between them. This is the default gap between columns in the tabular environment.
  2. The width of each \parbox is the width of its corresponding figure (determined with \wd) plus the width of the space between the figures ((\textwidth-\wd0-\wd1)/3) minus the gap between the \parboxes (6pt). This ensures that they are centered under their respective figures.

The trailing comments are required to prevent line breaks from getting expanded to spaces.

You must log in to answer this question.

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