8

In this example,

\documentclass{article}
\usepackage{graphicx}
\usepackage{subcaption}
\begin{document}
\begin{figure}
  \centering
  \begin{subfigure}[t]{0.33\textwidth}
    \centering
    \includegraphics[width=\textwidth]{example-image-a}
    \caption{a}
  \end{subfigure}
  \begin{subfigure}[t]{0.33\textwidth}
    \centering
    \includegraphics[width=\textwidth]{example-image-b}
    \caption{b}
  \end{subfigure}
  \begin{subfigure}[t]{0.33\textwidth}
    \centering
    \includegraphics[width=\textwidth]{example-image-c}
    \caption{c}
  \end{subfigure}
\end{figure}
\end{document}

I chose the subfigure width equally 1/3 with the rationale that the figure span \textwidth exactly. From the result,

Enter image description here

one can deduce that there is some overhead.

How do I optimally chose subfigure width so that the figure span textwidth exactly for N = 2, 3, 4, ... subfigures?

  • 2
    Real quick: all four \centering directives may be omitted. – Mico Dec 26 '17 at 0:19
6

What is happening is that between each subfigure you have a new line that, for TeX, is exactly the same thing as a space. So what you have is three subfigures with two spaces in between. To fix it, add a % after each subfigure so that TeX will not consider it as a space:

\documentclass{article}
\usepackage{graphicx}
\usepackage{subcaption}
\begin{document}
\begin{figure}
  \centering
  \begin{subfigure}[t]{0.33\textwidth}
    \centering% < useless
    \includegraphics[width=\textwidth]{example-image-a}
    \caption{a}
  \end{subfigure}% < HERE 
  \begin{subfigure}[t]{0.33\textwidth}
    \centering% < useless
    \includegraphics[width=\textwidth]{example-image-b}
    \caption{b}
  \end{subfigure}% < AND HERE
  \begin{subfigure}[t]{0.33\textwidth}
    \centering% < useless
    \includegraphics[width=\textwidth]{example-image-c}
    \caption{c}
  \end{subfigure}
\end{figure}
\end{document}

Edit:

Since my answer was chosen even with all the other answers down here, I felt the need to add a few explanations for the future generations ;)

Why 3 * 0.33\textwidth does not fit in \textwidth?

Firstly, as I said above, the major problem was that when TeX reads either a space or a new line character, it understands both as a space. The rule is different for multiple spaces or new lines. Multiple spaces are treated by TeX as a single space and multiple new lines are treated by TeX as a paragraph ending. For example, if you compile this:

\documentclass{article}
\usepackage[paperwidth=4in]{geometry}
\begin{document}
This is written
on      several
separate  lines
separated    by
a    new   line
character    or
by       spaces.


But when processed by \TeX, the result is two normal paragraphs!
\end{document}

you get this:

The code above compiled

This is quite obvious when writing only text, like in the example above. But the same applies when you are using figures. If you insert a new line between consecutive \includegraphics or subfigure environments, TeX will treat them as spaces!

In Viesturs' MWE, the subfigure environments are separated by new lines, which are treated by TeX as spaces.

To check the effect of the spaces in Viesturs' MWE, we can first measure the size of \textwidth with:

textwidth: \the\textwidth

and we get Textwidth, thus the width of the subfigures is 0.33\textwidth, which is exactly 113.85pt.

Furthermore, we can measure the space of the current font using:

space: \the\fontdimen2\font\space plus \the\fontdimen3\font\space minus \the\fontdimen4\font

and we get Space. For TeX, this means that the space is 3.333pt wide, but can be stretched by 1.666pt or shrinked by 1.111pt.

So, assuming that TeX will shrink the space as far as it can to try to fit the three subfigures in a single line, the layout would have three figures of 113.85pt, and two spaces of 3.333pt minus 1.111pt (= 2.222pt). So the with of the contents is 3 * 113.85pt + 2 * 2.222pt = 345.994pt, Which is 0.994pt larger than the available \textwidth. Thus TeX will give up on putting it in one line and break the line before inserting the third subfigure!

But Phelype, how do I fix this?!?!

Well, Jimmy, another couple of things about TeX is that:

  1. After TeX sees a % sign, it ignores everything that comes after it on the current line. This is why commenting works this way in TeX (and most programming languages, actually). But for the problem we're facing now, this is why the % sign makes TeX ignore the new line character between each subfigure.

  2. TeX ignores leading spaces! So the indentation before the following \begin{subfigure} is also ignored!

So, as far as TeX is concerned, this:

  \end{subfigure}% < HERE 
  \begin{subfigure}[t]{0.33\textwidth}

is exactly the same as this:

  \end{subfigure}\begin{subfigure}[t]{0.33\textwidth}
  %              ^ No spaces!!!

and observe that the second one does not have any space between the subfigures. Now, if we do the previous calculation without the spaces, we have 3 * 113.85pt = 341.55pt, which fits in the current \textwidth!

This may seem obvious to some, but for starters it's tricky to promptly see why 3 * 0.33\textwidth does not fit in \textwidth. A few months ago I frequently found myself naively changing 0.33\textwidth to 0.329\textwidth to make the figures fit on one line :P

Disclaimer: All the above is valid in normal typesetting mode. In verbatim, math, or other special environments the rules are different!

  • 1
    To reduce code clutter, you may wish to remove the three \centering directives contained inside the subfigure environments. – Mico Dec 26 '17 at 2:04
  • @Mico Thanks! I edited it in my answer (and a few other things too :P) – Phelype Oleinik Dec 26 '17 at 18:27
7

How to optimally chose subfigure widths so that the figure spans \textwidth exactly, for N = 2, 3, 4, ... subfigure environments?

  • First off, note that all four \centering directives in your code may (and, in fact, should!) be omitted.

  • Second, assuming you wish to leave a bit of whitespace between adjacent images, you should change the relative widths for three side-by-side subfigures from 0.33\textwidth to something like 0.3\textwidth or 0.31\textwidth. Similarly, use 0.23\textwidth or 0.24\textwidth for four side-by-side subfigures, and 0.48\textwidth for two side-by-side subfigures.

  • Finally, use \hfill directives to maximize the separation between the subfigures placed on a line.

enter image description here

\documentclass{article}
\usepackage{graphicx,subcaption}
\begin{document}
\begin{figure}
  \begin{subfigure}[t]{0.31\textwidth}
    \includegraphics[width=\textwidth]{example-image-a}
    \caption{a}
  \end{subfigure}\hfill%  % <-- \hfill is new
  \begin{subfigure}[t]{0.31\textwidth}
    \includegraphics[width=\textwidth]{example-image-b}
    \caption{b}
  \end{subfigure}\hfill%  % <-- \hfill is new
  \begin{subfigure}[t]{0.31\textwidth}
    \includegraphics[width=\textwidth]{example-image-c}
    \caption{c}
  \end{subfigure}

\bigskip\bigskip
  \begin{subfigure}[t]{0.23\textwidth}
    \includegraphics[width=\textwidth]{example-image-a}
    \caption{dd}
  \end{subfigure}\hfill%
  \begin{subfigure}[t]{0.23\textwidth}
    \includegraphics[width=\textwidth]{example-image-b}
    \caption{ee}
  \end{subfigure}\hfill%
  \begin{subfigure}[t]{0.23\textwidth}
    \includegraphics[width=\textwidth]{example-image-c}
    \caption{f\kern0ptf}
  \end{subfigure}\hfill%
  \begin{subfigure}[t]{0.23\textwidth}
    \includegraphics[width=\textwidth]{example-image-a}
    \caption{gg}
  \end{subfigure}

\caption{Seven subfigures}
\end{figure}
\end{document}
6

The following uses tabularx to automate the process of specifying the number of elements to distribute evenly across \textwidth:

enter image description here

\documentclass{article}

\usepackage{graphicx,subcaption,tabularx}

\newenvironment{distsubfig}[1]
  {\noindent\tabularx{\textwidth}{@{} *{#1}{X} @{}}}
  {\endtabularx\par}

\begin{document}

\begin{figure}
  \begin{distsubfig}{3}
    \includegraphics[width=\linewidth]{example-image-a}
    \caption{a}
    &
    \includegraphics[width=\linewidth]{example-image-b}
    \caption{b}
    &
    \includegraphics[width=\linewidth]{example-image-c}
    \caption{c}
  \end{distsubfig}

  \bigskip

  \begin{distsubfig}{5}
    \includegraphics[width=\linewidth]{example-image-a}
    \subcaption{a}
    &
    \includegraphics[width=\linewidth]{example-image-b}
    \subcaption{b}
    &
    \includegraphics[width=\linewidth]{example-image-c}
    \subcaption{c}
    &
    \includegraphics[width=\linewidth]{example-image-a}
    \subcaption{e}
    &
    \includegraphics[width=\linewidth]{example-image-b}
    \subcaption{f}
  \end{distsubfig}
  \begin{distsubfig}{4}
    \includegraphics[width=\linewidth]{example-image-c}
    \subcaption{g}
    &
    \includegraphics[width=\linewidth]{example-image-a}
    \subcaption{h}
    &
    \includegraphics[width=\linewidth]{example-image-b}
    \subcaption{i}
    &
    \includegraphics[width=\linewidth]{example-image-c}
    \subcaption{j}
  \end{distsubfig}
  \caption{A figure caption}
\end{figure}

\end{document}

The distsubfig environment takes a single argument: the number of subfloats to distribute evenly across \textwidth; alternatively, the number of X-columns to use in a tabularx. The gap between the subfloats are \tabcolsep, just like in any tabular environment (and can be changed).

  • 2
    +1. For the benefit of those readers who are unfamiliar with some of the parameters of LaTeX's tabular-like environments, you may want to (a) mention the default value of \tabcolsep and (b) offer a suggestion (e.g., \setlength{\tabcolsep}[...} how one might change the value of this parameter. – Mico Dec 26 '17 at 7:58
6

Here's a version where you just need to specify the number of subfigures per row.

\documentclass{article}
\usepackage{subcaption}
\usepackage{graphicx}
\usepackage{showframe}

\newlength{\minsubgap}
\newlength{\maxsubgap}
\setlength{\minsubgap}{3pt}  % set to suit
\setlength{\maxsubgap}{12pt} % set to suit

\newlength{\viesturssubfigurewidth}
\newlength{\viesturssubfiguregap}

\newenvironment{bunchofsubfigures}[1] % #1 = images per row
 {%
  \setlength{\viesturssubfiguregap}{%
    \dimexpr\minsubgap+(\maxsubgap-\minsubgap)*2/(#1)\relax
  }%
  \setlength{\viesturssubfigurewidth}{%
    \dimexpr(\textwidth-\viesturssubfiguregap*(#1-1))/(#1)\relax
  }
  \setlength{\leftskip}{-0.1pt plus 1fil}%
  \setlength{\rightskip}{0pt}%
 }
 {{\parfillskip=-0.1pt plus 1fil\par}}
\newcommand{\viesturssub}[2]{% #1 = subcaption, #2 = image name
  \subcaptionbox{#1}{\includegraphics[width=\viesturssubfigurewidth]{#2}}%
  \hspace{\viesturssubfiguregap}\ignorespaces
}

\begin{document}

\begin{figure}[htp]

\begin{bunchofsubfigures}{2}
\viesturssub{Caption}{example-image}
\viesturssub{Caption}{example-image}
\viesturssub{Caption}{example-image}
\end{bunchofsubfigures}

\caption{Full caption}

\end{figure}

\begin{figure}[htp]

\begin{bunchofsubfigures}{3}
\viesturssub{Caption}{example-image}
\viesturssub{Caption}{example-image}
\viesturssub{Caption}{example-image}
\viesturssub{Caption}{example-image}
\viesturssub{Caption}{example-image}
\viesturssub{Caption}{example-image}
\end{bunchofsubfigures}

\caption{Full caption}

\end{figure}

\begin{figure}[htp]

\begin{bunchofsubfigures}{5}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\end{bunchofsubfigures}

\caption{Full caption}

\end{figure}

\begin{figure}[htp]

\begin{bunchofsubfigures}{6}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\end{bunchofsubfigures}

\caption{Full caption}

\end{figure}

\begin{figure}[htp]

\begin{bunchofsubfigures}{7}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\end{bunchofsubfigures}

\caption{Full caption}

\end{figure}

\begin{figure}[htp]

\begin{bunchofsubfigures}{8}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\viesturssub{}{example-image}
\end{bunchofsubfigures}

\caption{Full caption}

\end{figure}

\end{document}

The \maxsubgap is used between two figures per row; the gap goes asymptotically to \minsubgap as the number of figures per row increases. Choose both values to suit your needs.

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.