Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I would like to place two figures side by side (not subfigures) and what’s more, I’d like to let the figures spill into the outer margin (since they are too wide for the the text width. Like this:

screenshot

(Black lines delimit the page borders. Full page [pdf])

The following actually works very nicely:

\begin{figure}[h]
  \setcapwidth{0.6\textwidth}
  \begin{flushright}
    \hspace{-\marginfigwidth}%
    \begin{minipage}[t]{0.6\textwidth}
      \centering
      \includegraphics{gfx-1}
      \caption{Caption 1}
    \end{minipage}%
    \hspace{1cm}%
    \begin{minipage}[t]{0.6\textwidth}
      \centering
      \includegraphics{gfx-2}
      \caption{Caption 2}
      \label{fig:free-lunch}
    \end{minipage}
  \end{flushright}
\end{figure}

Unfortunately, there’s a snag: this only works on the left hand page, since I force it into the margin via \hspace{-\marginfigwidth} command (where \marginfigwidth is defined as \marginparwidth + \marginparsep).

I can’t wrap my head around how this must be changed to work on all pages. If I just remove the negative hspace on a right-hand page, the page will automatically break. I can of course wrap the whole thing into yet another minipage but this doesn’t work since it won’t respect the specified \hspace between the figures and spill over the page border.

The wrapfigure environment doesn’t help me either since that is designed to work with single pictures only.

How can I make this code work independent of the page (left/right) so that it always spills into the outer margin?

share|improve this question

4 Answers 4

up vote 19 down vote accepted

Use either the ifoddpage or the changepage package to check on which page the figure is. It needs two latex runs to determine the correct page number. If the changepage package is used it should be loaded with the strict option, because otherwise the used page number might not be correct in all cases (when TeX reads more material to look for a page break etc.). Alternatively the macro \strictpagecheck can be placed before \checkoddpage.

The trick is to use \makebox[\textwidth] so that the box is officially only \textwidth long which also avoids "Overfull hbox" errors. Then the second optional argument of \makebox is used to align it either to the right or left:

\documentclass{scrbook}
\usepackage{graphicx}
\usepackage{ifoddpage}
%or: \usepackage[strict]{changepage}
\begin{document}

\begin{figure}[h]
  %\setcapwidth{0.6\textwidth}
  \checkoddpage
  \edef\side{\ifoddpage l\else r\fi}%
  \makebox[\textwidth][\side]{%
    \begin{minipage}[t]{0.59\textwidth}
      \centering
      \includegraphics[width=\textwidth]{gfx-1}
      \caption{Caption 1}
    \end{minipage}%
    \hfill
    \begin{minipage}[t]{0.59\textwidth}
      \centering
      \includegraphics[width=\textwidth]{gfx-2}
      \caption{Caption 2}
      \label{fig:free-lunch}
    \end{minipage}%
  }%
\end{figure}
\end{document}

I have something like this as an example on my website. See also this TeX FAQ from where I got the idea.

share|improve this answer
    
Nice package! This is what I'm looking for. –  Leo Liu Feb 7 '11 at 19:42
    
@Leo: I got the idea from the TeX FAQ. –  Martin Scharrer Feb 7 '11 at 20:00
    
Thanks. I didn't read all UK-FAQ. I'm writing a book and use \ifodd\c@page before, which is wrong at the beginning of a page. I knew the trick to make a cross-reference for every \if, but I didn't implement it yet. Now I needn't do it myself. –  Leo Liu Feb 7 '11 at 20:11
2  
This answer nailed it. Great. Small precaution for other users of this solution: sometimes it won’t work. To fix this, pass the option strict to the package or put \strictpagecheck before the \checkoddpage. –  Konrad Rudolph Feb 7 '11 at 20:39
    
Thanks @Konrad, I added this option to my answer. –  Martin Scharrer Feb 7 '11 at 21:04

\Figure[Width]{imag1}{cap1}{imag2}{cap2}. The width is by default textwidth+marginparwidth. But it can still be increased with \marginparsep or any other value.

\documentclass[ngerman]{book}
\usepackage[demo]{graphicx}

\usepackage{babel,blindtext,ifthen}
\newlength\fullwidth\fullwidth=\textwidth
\advance\fullwidth by \marginparwidth

\newcommand\Figure[5][\fullwidth]{%
  \label{\thefigure:WideFigure}
  \begin{figure}[!htb]%
    \abovecaptionskip=0pt\belowcaptionskip=0pt
    \ifthenelse{\isodd{\pageref{\thefigure:WideFigure}}}{}{\hspace*{-\marginparwidth}}%
    \begin{minipage}{#1}
     \begin{minipage}[b]{0.45\linewidth}\centering
     \includegraphics[width=0.95\linewidth]{#2}
     \caption{#3}
     \end{minipage}\hfill%
     \begin{minipage}[b]{0.45\linewidth}\centering
     \includegraphics[width=0.95\linewidth]{#4}
     \caption{#5}
     \end{minipage}%
  \end{minipage}%
 \end{figure}}


\begin{document}

\blindtext
\Figure{foo}{what a wonderful caption}%
       {foo}{What another wonderful caption}

\blindtext[4]
\Figure{foo}{what a wonderful caption}%
       {foo}{What another wonderful caption}

\end{document}

enter image description here

share|improve this answer

I had the same problem, but in addition I wanted to integrate the subfig package and I needed to put it into an external command, because I use different layouts (one of them does not have a margin).

My TeX-Macro skills are not huge, therefore the macros are huge ;-) But it works for me (for now).

\newlength\fullmarginwidth
\fullmarginwidth=\marginparwidth
\advance\fullmarginwidth by \marginparsep

\newlength\fullwidth
\fullwidth=\textwidth
\advance\fullwidth by \fullmarginwidth

%Parameters: [keyvals (see below)]{file}{caption}
\makeatletter
  \define@key[Marfig]{bigfig}{pos}{\def\MfBfPos{#1}}
  \define@key[Marfig]{bigfig}{relsize}{\def\MfBfRelSize{#1}}
  \define@key[Marfig]{bigfig}{label}{\def\MfBfLabel{#1}}
  \define@key[Marfig]{bigfig}{shortcaption}{\def\MfBfShortCaption{#1}}
\makeatother
\newcommand{\bigfigure}[3][]{%
  \begingroup
    \setkeys[Marfig]{bigfig}{ pos=!htp,
                              label={fig:#2},
                              shortcaption={#3},
                              relsize=0.95}
    \setkeys[Marfig]{bigfig}{#1}
    \def\efigure{\begin{figure}}%
    \expandafter\efigure\expandafter[\MfBfPos]
      \checkoddpage
      \edef\side{\ifoddpage l\else r\fi}
      \makebox[\textwidth][\side]{% 
        \begin{minipage}[t]{\fullwidth}
          \centering
          \includegraphics[width=\MfBfRelSize\textwidth]{#2}
          \caption[\MfBfShortCaption]{#3}
          \label{\MfBfLabel}
        \end{minipage}
      }%
    \end{figure}
  \endgroup
}

\makeatletter
  \define@key[Marfig]{bigdblfig}{pos}{\def\MfBDfPos{#1}}
  \define@key[Marfig]{bigdblfig}{mainrelsize}{\def\MfBDfMainRelSize{#1}}
  \define@key[Marfig]{bigdblfig}{mainlabel}{\def\MfBDfMainLabel{#1}}
  \define@key[Marfig]{bigdblfig}{maincaption}{\def\MfBDfMainCaption{#1}}
  \define@key[Marfig]{bigdblfig}{mainshortcaption}{\def\MfBDfMainShortCaption{#1}}
  \define@key[Marfig]{bigdblfig}{leftrelsize}{\def\MfBDfLeftRelSize{#1}}
  \define@key[Marfig]{bigdblfig}{leftlabel}{\def\MfBDfLeftLabel{#1}}
  \define@key[Marfig]{bigdblfig}{leftcaption}{\def\MfBDfLeftCaption{#1}}
  \define@key[Marfig]{bigdblfig}{leftshortcaption}{\def\MfBDfLeftShortCaption{#1}}
  \define@key[Marfig]{bigdblfig}{rightrelsize}{\def\MfBDfRightRelSize{#1}}
  \define@key[Marfig]{bigdblfig}{rightlabel}{\def\MfBDfRightLabel{#1}}
  \define@key[Marfig]{bigdblfig}{rightcaption}{\def\MfBDfRightCaption{#1}}
  \define@key[Marfig]{bigdblfig}{rightshortcaption}{\def\MfBDfRightShortCaption{#1}}
\makeatother


%Parameters: [keyvals (see below)]{file-left}{file-right}
\newcommand{\bigdoublefigure}[3][]{%
  \begingroup
    %Default values:
    \setkeys[Marfig]{bigdblfig}{pos=!htp,
                                mainrelsize=0.95,
                                mainlabel={fig:#2-#3},
                                maincaption={},
                                mainshortcaption={},%
                                leftrelsize=0.45,
                                leftlabel={fig:#2-left},
                                leftcaption={},
                                leftshortcaption={},%
                                rightrelsize=0.45,
                                rightlabel={fig:#2-right},
                                rightcaption={},
                                rightshortcaption={}}
    %User provided values:
    \setkeys[Marfig]{bigdblfig}{#1}
    \def\efigure{\begin{figure}}%
    \expandafter\efigure\expandafter[\MfBDfPos]
      %Check on which side whe are (right or left)
      \checkoddpage
      \edef\side{\ifoddpage l\else r\fi}
      %Ensure there will be no overfull box message
      \makebox[\textwidth][\side]{% 
        \begin{minipage}{\MfBDfMainRelSize\fullwidth}
          \centering
          \ifthenelse{\equal{\MfBDfLeftCaption}{}}%
          {
            %left subfloat without captions
            \subfloat{%
              \includegraphics[width=\MfBDfLeftRelSize\textwidth]{#2}
              \label{\MfBDfLeftLabel}
            }          
          }
          {
            \ifthenelse{\equal{\MfBDfLeftCaption}{}}%
            {
              %left subfloat with same captions
              \subfloat[\MfBDfLeftCaption][\MfBDfLeftCaption]{%
                \includegraphics[width=\MfBDfLeftRelSize\textwidth]{#2}
                \label{\MfBDfLeftLabel}
              }
            }
            {
              %left subfloat with different captions
              \subfloat[\MfBDfLeftShortCaption][\MfBDfLeftCaption]{%
                \includegraphics[width=\MfBDfLeftRelSize\textwidth]{#2}
                \label{\MfBDfLeftLabel}
              }
            }
          }
          \hfill
           \ifthenelse{\equal{\MfBDfRightCaption}{}}%
          {
            %right subfloat without captions
            \subfloat{%
              \includegraphics[width=\MfBDfRightRelSize\textwidth]{#3}
              \label{\MfBDfRightLabel}
            }
          }
          {
            \ifthenelse{\equal{\MfBDfRightShortCaption}{}}%
            {
              %right subfloat with same captions
              \subfloat[\MfBDfRightCaption][\MfBDfRightCaption]{%
                \includegraphics[width=\MfBDfRightRelSize\textwidth]{#3}
                \label{\MfBDfRightLabel}
              }
            }
            {
              %right subfloat with different captions
              \subfloat[\MfBDfRightShortCaption][\MfBDfRightCaption]{%
                \includegraphics[width=\MfBDfRightRelSize\textwidth]{#3}
                \label{\MfBDfRightLabel}
              }
            }
          }
          \ifthenelse{\equal{\MfBDfMainCaption}{}}
          {
            %no main caption
          }
          {
            \ifthenelse{\equal{\MfBDfMainShortCaption}{}}
            {
              %same main captions
              \caption[\MfBDfMainCaption]{\MfBDfMainCaption}
            }
            {
              %different main captions
              \caption[\MfBDfMainShortCaption]{\MfBDfMainCaption}
            }
          }
          \label{\MfBDfMainLabel}
        \end{minipage}
      }
    \end{figure}
  \endgroup
}
share|improve this answer
    
Which key-value package have you used to implement your code? As common in some other instances, there are many repetitive and similar calls to \definekey here :). Can we be more efficient (saving estate and tokens) by using a loop? –  Ahmed Musa Feb 18 '11 at 15:06
    
Thanks for your improvements. I didn't test it though (yet). –  B3ret Feb 19 '11 at 15:13

@B3ret:

You can try the following code. I have thoroughly tested the key definition part, but not the figure inclusion portion of the code. That is left to the user.

\documentclass{article}
\usepackage{graphicx}
\usepackage{lipsum}
\usepackage[strict]{changepage}
\usepackage{xkeyval}

% Note: \setkeys from 'xkeyval' strips up to 3 levels of outer braces.

\makeatletter
\newcommand*\ifcmdempty[1]{%
  \@nameuse{@\expandafter\ifx\expandafter\\\@gobble#1.\\%
    second\else first\fi oftwo}%
  {\@nameuse{@\ifx#1\@empty first\else second\fi oftwo}}%
  \@secondoftwo
}
\newcommand\@expandarg[2]{%
  \begingroup
  \protected@edef\reserved@a{\endgroup\unexpanded{#1}{#2}}\reserved@a
}
\newcommand\@expandargnobrace[2]{%
  \begingroup
  \protected@edef\reserved@a{\endgroup\unexpanded{#1}#2}\reserved@a
 }
\newcommand*\ifpdfstrcmp[2]{%
  \@nameuse{@\ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=\z@
    first\else second\fi oftwo}%
}
\newcommand*\makecs[1]{\@expandonce{\csname#1\endcsname}}
\newcommand*\putsubfloat[6]{%
  \begingroup
  \protected@edef\reserved@a{\endgroup
    \ifnum#1=\z@\else\noexpand\subfloat[\makecs{mfbdf@#2}][\makecs{mfbdf@#3}]{\fi
    \noexpand\includegraphics[width=\makecs{mfbdf@#4}\textwidth]{\unexpanded{#5}}%
    \noexpand\label{\makecs{mfbdf@#6}}%
    \ifnum#1=\z@\else}\fi
  }%
  \reserved@a
}
\edef\fullwidth{\the\dimexpr\textwidth+\marginparwidth+\marginparsep}

% \Define@Keys is adapted from the development version of keyreader package.
% The new facilities of keyreader package are more extensive
% than seen here:
\newcommand*\define@keysloop[1]{\@define@keysloop#1,\defkey@nil,}
\def\@define@keysloop#1,{%
  \begingroup\edef\reserved@a{\unexpanded{#1}}%
  \expandafter\endgroup\ifx\reserved@a\defkey@nnil\else
    \define@keysdo{#1}\relax
    \expandafter\@define@keysloop
  \fi
}
\def\defkey@nnil{\defkey@nil}
\newcommand*\@expandonce[1]{\unexpanded\expandafter{#1}}
\newcommand*\Define@Keys{\@testopt\@define@keys{KV}}
\def\@define@keys[#1]#2{\@testopt{\@@define@keys{#1}{#2}}{mp@}}
\def\@@define@keys#1#2[#3]#4{%
  \KV@@sp@def\keyprefix{#1}%
  \KV@@sp@def\keyfamily{#2}%
  \KV@@sp@def\macroprefix{#3}%
  \def\key@vals{}%
  \def\define@keys@do##1=##2=##3\defkey@nil{%
    \expandafter\ifx\expandafter\\\@gobble##1.\\%
      \@latex@error{Empty key name}\@ehc
    \fi
    \define@keys@@do##1/##2//\defkey@nil
  }%
  \def\define@keys@@do##1/##2/##3/##4\defkey@nil{%
    \KV@@sp@def\keyname{##1}%
    \KV@@sp@def\keydefault{##2}%
    \edef\key@vals{%
      \ifcmdempty\key@vals{}{\@expandonce\key@vals,}%
      \@expandonce\keyname=\@expandonce\keydefault
    }%
    \edef\reserved@a{%
      [\keyprefix]{\keyfamily}[\macroprefix]{\keyname}%
      [\@expandonce\keydefault]{\unexpanded{##3}}%
    }%
    \expandafter\ifpdfstrcmp\expandafter{\keydefault}{true}{%
      \expandafter\define@boolkey
    }{%
      \expandafter\ifpdfstrcmp\expandafter{\keydefault}{false}{%
        \expandafter\define@boolkey
      }{%
        \expandafter\define@cmdkey
      }%
    }%
    \reserved@a
  }%
  \long\def\define@keysdo##1{\define@keys@do##1==\defkey@nil}%
  \define@keysloop{#4}%
  \edef\reserved@a{%
    \noexpand\setkeys[\keyprefix]{\keyfamily}{\@expandonce\key@vals}%
  }%
  \reserved@a
}
\Define@Keys[KV]{bigfig}[mfbf@]{pos=!htp,label,shortcaption,relsize=0.95,
  testbool=true/\ifmfbf@testbool\def\testfunc##1{xx##1xx}\fi}
% Parameters: [key-val pairs]{file}{caption}
\newcommand{\bigfigure}[3][]{%
  % Default values:
  \setkeys[KV]{bigfig}{pos=!htp,label=fig:#2,
    shortcaption={{{#3}}},relsize=0.95}%
  % User-provided values:
  \ifx\\#1\\\else\setkeys[KV]{bigfig}{#1}\fi
  \@expandargnobrace{\begin{figure}}{[\mfbf@pos]}%
    \checkoddpage
    \@expandargnobrace{\makebox[\textwidth]}{[\ifoddpage l\else r\fi]}{%
      \begin{minipage}[t]{\fullwidth}%
        \centering
        \includegraphics[width=\mfbf@relsize\textwidth]{#2}%
        \caption[\mfbf@shortcaption]{#3}%
        \label{\mfbf@label}%
      \end{minipage}%
    }% 
  \end{figure}%
}
\Define@Keys[KV]{bigdblfig}[mfbdf@]{pos=!htp,mainrelsize=0.95,
    mainlabel=fig:mainlabel,maincaption,mainshortcaption,
    leftrelsize=0.45,leftlabel=fig:leftlabel,leftcaption,
    leftshortcaption,rightrelsize=0.45,rightlabel=fig:rightlabel,
    rightcaption,rightshortcaption
}
% [key-value pairs]{file-left}{file-right}
\newcommand{\bigdoublefigure}[3][]{%
  % The keyreader package avoids this type of repetition:
  \setkeys[KV]{bigdblfig}{pos=!htp,mainrelsize=0.95,
    mainlabel={fig:#2-#3},maincaption=,mainshortcaption=,
    leftrelsize=0.45,leftlabel={fig:#2-left},leftcaption=,
    leftshortcaption=,rightrelsize=0.45,rightlabel={fig:#2-right},
    rightcaption=,rightshortcaption=
  }%
  \ifx\\#1\\\else\setkeys[KV]{bigdblfig}{#1}\fi
  \@expandargnobrace{\begin{figure}}{[\mfbdf@pos]}%
    \checkoddpage
     \@expandargnobrace{\makebox[\textwidth]}{[\ifoddpage l\else r\fi]}{%  
        \begin{minipage}{\mfbdf@mainrelsize\fullwidth}%
          \centering 
          \ifcmdempty\mfbdf@leftcaption{%
            \putsubfloat\z@{}{}{leftrelsize}{#2}{leftlabel}%
          }{%
            \ifcmdempty\mfbdf@leftshortcaption{%
              \putsubfloat\@ne{leftcaption}{leftcaption}{leftrelsize}{#2}{leftlabel}%
            }{%
              \putsubfloat\@ne{leftshortcaption}{leftcaption}{leftrelsize}{#2}{leftlabel}%
            }%
          }%
          \hfill
          \ifcmdempty\mfbdf@rightcaption{%
            \putsubfloat\z@{}{}{rightrelsize}{#3}{rightlabel}%
          }{%
            \ifcmdempty\mfbdf@rightshortcaption{%
              \putsubfloat\@ne{rightcaption}{rightcaption}{rightrelsize}{#3}{rightlabel}%
            }{%
              \putsubfloat\@ne{rightshortcaption}{rightcaption}{rightrelsize}{#3}{rightlabel}%
            }%
          }%
          \ifcmdempty\mfbdf@maincaption{}{%
            \ifcmdempty\mfbdf@mainshortcaption{%
              \caption[\mfbdf@maincaption]{\mfbdf@maincaption}%
            }{%
              \caption[\mfbdf@mainshortcaption]{\mfbdf@maincaption}%
            }%
          }%
          \label{\mfbdf@mainlabel}%
        \end{minipage}
    }%
  \end{figure}
}
\makeatother

\begin{document}

\lipsum[1-2]

\end{document}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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