7

What I currently have is this:

before

\documentclass{article}
\usepackage{mwe}
\usepackage{subcaption}
\usepackage{calc}
\begin{document}
  \begin{figure}
    \begin{subfigure}{\linewidth}
      \begin{subfigure}{\linewidth/3 - 2em}
        \includegraphics[width=\linewidth]{example-image-1x1}
      \end{subfigure}\hfill
      \begin{subfigure}{\linewidth/3 - 2em}
        \includegraphics[width=\linewidth]{example-image-1x1}
      \end{subfigure}\hfill
      \begin{subfigure}{\linewidth/3 - 2em}
        \includegraphics[width=\linewidth]{example-image-1x1}
      \end{subfigure}
      \caption{Row 1}
    \end{subfigure}
    \par\bigskip
    \begin{subfigure}{\linewidth}
      \setcounter{subfigure}{0}%
      {
        \renewcommand\thesubfigure{\roman{subfigure}}
        \begin{subfigure}{\linewidth/3 - 2em}
          \includegraphics[width=\linewidth]{example-image-1x1}
          \caption{Column a}
        \end{subfigure}\hfill
        \begin{subfigure}{\linewidth/3 - 2em}
          \includegraphics[width=\linewidth]{example-image-1x1}
          \caption{Column b}
        \end{subfigure}\hfill
        \begin{subfigure}{\linewidth/3 - 2em}
          \includegraphics[width=\linewidth]{example-image-1x1}
          \caption{Column c}
        \end{subfigure}
      }%
      \setcounter{subfigure}{1}%
      \caption{Row 2}
    \end{subfigure}
  \end{figure}
\end{document}

How can I move the row captions to appear in the margins, rotated?

after

I've tried using \rotatebox, but that just seems to error when it includes a caption

  • First, you don't NEED to use \caption. Subcaptions do not show up in the \listoffigure, and the subfigure counter is inapropriate here. Plain text will do. – John Kormylo May 28 '17 at 14:57
  • @JohnKormylo: I'd like to reference the rows and columns in the text with \cref if possible, rather than resorting to \cref{thefigure}(a) – Eric May 28 '17 at 15:09
4

This solution uses a tabular (left shifted into the margin slightly) to do all the alignment. It relies on the fact that the images are the same height as width (otherwise one would have to measure the image height).

Two new counters were introduced to allow \labels. The imagecolumn counter will automatically be incremented in each I column. Labels will store whatever you put into \theimagecolumn.

\documentclass{article}
\usepackage{graphicx}
\usepackage{array}
\usepackage{showframe}% debuggin tool

\newcounter{imagerow}[figure]
\newcounter{imagecolumn}[imagerow]
\renewcommand{\theimagecolumn}{Row \arabic{imagerow} Column \arabic{imagecolumn}}

\newcolumntype{I}{>{\refstepcounter{imagecolumn}}{c}<{}}

\newlength{\imagewidth}

\begin{document}
  \begin{figure}
    \def\arraystretch{0}% remove \arraystretch\dp\strutbox from row gap
    \setlength{\imagewidth}{\dimexpr \textwidth - 4\tabcolsep}% each gap takes 2\tabcolsep
    \divide \imagewidth by 3
    \hspace*{\dimexpr -\baselineskip - 2\tabcolsep}% move first column into margin
    \begin{tabular}{@{}cIII@{}}
      \stepcounter{imagerow}\raisebox{0.5\imagewidth}{\rotatebox[origin=c]{90}%
        {\strut Row \theimagerow}} &
      \includegraphics[width=\imagewidth]{example-image-1x1} &
      \includegraphics[width=\imagewidth]{example-image-1x1}\label{example} &
      \includegraphics[width=\imagewidth]{example-image-1x1} \\[2\tabcolsep]% adds gap between rows
      \stepcounter{imagerow}\raisebox{0.5\imagewidth}{\rotatebox[origin=c]{90}%
        {\strut Row \theimagerow}} &
      \includegraphics[width=\imagewidth]{example-image-1x1} &
      \includegraphics[width=\imagewidth]{example-image-1x1} &
      \includegraphics[width=\imagewidth]{example-image-1x1} \\[2\tabcolsep]
        \setcounter{imagecolumn}{0} &% \stepcounter{imagerow} will also work
        Column \arabic{imagecolumn} &
        Column \arabic{imagecolumn} &
        Column \arabic{imagecolumn}
    \end{tabular}
  \end{figure}
Example reference to image at \ref{example}.
\end{document}

demo

  • Reading this again, this looks great - thanks! Could you explain the reason behind \baselineskip? And presumably \divide ... and the line above could be combined with the calc package? – Eric May 28 '17 at 23:38
  • 1
    To move the first column into the margin, you have to know how wide it is, and \baselineskip was my first guess. If that hadn't worked I would have tried \ht\strutbox+\dp\strutbox. You can do the \imagewidth calculation in one line without using the calc package (0.333\textwidth-1.333\tabcolsep, but then I would have to explain where the numbers came from. – John Kormylo May 29 '17 at 2:21
  • That second question was asking if \setlength{\imagewidth}{(\textwidth - 4\tabcolsep)/3} would work with calc loaded. Regarding \baselineskip, presumably you could ask for the height of the box you're actually using somehow, to allow multi-line row headings? – Eric May 29 '17 at 10:02
  • Presumably. I've never actually read the calc manual (didn't see any point). And yes, one could always measure the box height (or width after rotation). Using \sbox0 and \ht0 is fastest, but \heightof will also work. – John Kormylo May 29 '17 at 10:53
0

This doesn't work with \caption on the row, but it does at least look right:

enter image description here

The text itself is positioned with

\makebox[0pt]{\rotatebox[origin=c]{90}{
   (a) Row 1
}\hspace*{2em}}%

Note that I had to add a full new row for the column captions, as they would otherwise mess with the vertical alignment of the row captions.

The full code is

\documentclass{article}
\usepackage{mwe}% or load ’graphicx’ and ’blindtext’ manually
\usepackage{subcaption}
\usepackage{calc}
\begin{document}
  \blindtext
  \begin{figure}[h!]
    \begin{subfigure}{\linewidth}
      \makebox[0pt]{\rotatebox[origin=c]{90}{
        (a) Row 1
      }\hspace*{2em}}%
      \begin{subfigure}{\linewidth/3 - 2em}
        \includegraphics[width=\linewidth]{example-image-1x1}
      \end{subfigure}\hfill
      \begin{subfigure}{\linewidth/3 - 2em}
        \includegraphics[width=\linewidth]{example-image-1x1}
      \end{subfigure}\hfill
      \begin{subfigure}{\linewidth/3 - 2em}
        \includegraphics[width=\linewidth]{example-image-1x1}
      \end{subfigure}
    \end{subfigure}
    \par\bigskip
    \begin{subfigure}{\linewidth}
      \makebox[0pt]{\rotatebox[origin=c]{90}{
        (a) Row 1
      }\hspace*{2em}}%
      \begin{subfigure}{\linewidth/3 - 2em}
        \includegraphics[width=\linewidth]{example-image-1x1}
      \end{subfigure}\hfill
      \begin{subfigure}{\linewidth/3 - 2em}
        \includegraphics[width=\linewidth]{example-image-1x1}
      \end{subfigure}\hfill
      \begin{subfigure}{\linewidth/3 - 2em}
        \includegraphics[width=\linewidth]{example-image-1x1}
      \end{subfigure}
    \end{subfigure}
    \par\vskip \abovecaptionskip
    \begin{subfigure}{\linewidth}
      \setcounter{subfigure}{0}%
      \renewcommand\thesubfigure{\roman{subfigure}}
      \begin{subfigure}{\linewidth/3 - 2em}
        \caption{Column a}
      \end{subfigure}\hfill
      \begin{subfigure}{\linewidth/3 - 2em}
        \caption{Column b}
      \end{subfigure}\hfill
      \begin{subfigure}{\linewidth/3 - 2em}
        \caption{Column c}
      \end{subfigure}
    \end{subfigure}
  \end{figure}
\end{document}
  • As an aside - if I remove \bigskip, there is still a gap between the rows. How do I remove this gap, and where does it come from? – Eric May 28 '17 at 15:14

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.