1

I'm using the Tufte class and I want to create a margin figure that is larger than the margin, making the text wrap around it. Any tips of how I might do that? I tried adapting the @tufte@margin@floatbox to get a third argument for the minipage width, but I'm failing miserably. Here's what I got so far:

\newsavebox{\myfloatboxwider}
\newenvironment{myfloatwider}[3][-1.2ex]%
  {\FloatBarrier% process all floats before this point so the figure/table numbers stay in order.
  \begin{lrbox}{\myfloatboxwider}%
  \hspace*{-\marginparwidth}%
  \begin{minipage}{#3}%
    \@tufte@caption@font%
    \def\@captype{#2}%
    \hbox{}\vspace*{#1}%
    \@tufte@caption@justification%
    \@tufte@margin@par%
    \noindent%
  }
  {\end{minipage}%
  \end{lrbox}%
  \marginpar{\usebox{\myfloatboxwider}}%
  }

\newenvironment{marginfigurewider}[2][-1.2ex]% {\begin{myfloatwider}[#1]{figure}{#2}} {\end{myfloatwider}}

To use like this

\begin{marginfigurewider}[1.2ex]{2.0\marginparwidth}%
  \includegraphics[width=\linewidth]{myimage.jpg}
  \caption{Some caption.}
  \label{fig:somefig}
\end{marginfigurewider}

However there are two problems left that I cannot solve:

  1. The hspace should actually be #3-\marginparwidth, but I can't find a way to make this calculation.
  2. The main text does not wrap around it. Do I need something like wrapfig for this?

Update

This achieves more or less what I want:

\setlength\columnsep{\marginparsep}
\begin{wrapfigure}{O}[\dimexpr \marginparwidth+\marginparsep]{2.0\marginparwidth}
  \FloatBarrier%
  \vspace{-0.7\baselineskip}
  \begin{minipage}[b]{2.0\marginparwidth}
    \includegraphics[width=\linewidth]{myimage.jpg}
    \caption{Some caption.}
    \label{fig:somefig}
  \end{minipage}
\end{wrapfigure}

There are still two problems:

  1. Side notes, like cite, are overlaid over the image, not floated down below it.
  2. I can't make it work as a \newenvironment. Nothing shows, and width=\linewidth is flagged as not a number. I can live by using the code manually, but it'd be nicer if it was an environment. Attempt is below:

\newenvironment{marginfigurewide}[1]%
  {\FloatBarrier%
  \setlength\columnsep{\marginparsep}%
  \begin{wrapfigure}{O}[\dimexpr \marginparwidth+\marginparsep]{2.0\marginparwidth}%
      \vspace{-0.7\baselineskip}%
      \begin{minipage}[b]{2.0\marginparwidth}
  }
  {\end{minipage}%
  \end{wrapfigure}
  }
Sebastiano
  • 54,118
brunobg
  • 153

1 Answers1

1

I had the bright idea of reserving blank space in the margin using \marginpar. However, wrapfigure will still overlap any pre-existing margin material. I don't know of any way to delay the start of wrapfigure until the margin is empty (except manually).

Also, I don't know why \wrapfigure works and \begin{wrapfigure} doesn't, but it probably has something to do with local vs. global values.

\documentclass{tufte-book}
\usepackage{graphicx}
\usepackage{wrapfig}
\usepackage{marginfix}

\usepackage{lipsum} \usepackage{showframe}

\newsavebox{\marginbox}

\makeatletter \newenvironment{marginfigurewide}[1]% #1 = width {\begin{lrbox}{\marginbox}% \def@captype{figure}% \begin{minipage}{#1}}% {\end{minipage}\end{lrbox}% %\setlength{\intextsep}{0pt}% \setlength{\columnsep}{\marginparsep}% \wrapfigure{r}[\dimexpr \marginparwidth+\marginparsep]{\wd\marginbox} \usebox\marginbox \endwrapfigure \marginpar{\rule{0pt}{\dimexpr \ht\marginbox+\dp\marginbox+2\intextsep}}}% reserve space in margin \makeatother

\begin{document}

\begin{marginfigurewide}{2\marginparwidth} \includegraphics[width=\linewidth]{example-image} \caption{Some caption.} \label{fig:somefig} \end{marginfigurewide}

test\sidenote{\LipsumPar{2}}

\LipsumPar{1}

\end{document}


The version will overlap the bottom of the page.

\documentclass[twoside]{tufte-book}
\usepackage{graphicx}
\usepackage{wrapfig}
\usepackage{marginfix}

\usepackage{lipsum} \usepackage{showframe}

\newsavebox{\marginbox}

\makeatletter \newenvironment{marginfigurewide}[1]% #1 = width {\begin{lrbox}{\marginbox}% \def@captype{figure}% \begin{minipage}{#1}}% {\end{minipage}\end{lrbox}% \setlength{\columnsep}{\marginparsep}% \dimen0=\dimexpr \pagegoal-\pagetotal-\ht\strutbox\relax% remaining space on page \dimen1=\dimexpr \ht\marginbox+\dp\marginbox+\intextsep\relax% size of figure \ifdim\dimen1<\dimen0% fits page \wrapfigure{r}[\dimexpr \marginparwidth+\marginparsep]{\wd\marginbox} \usebox\marginbox \endwrapfigure \marginpar{\rule{0pt}{\dimexpr \ht\marginbox+\dp\marginbox+2\intextsep}}% reserve space in margin \else% overlaps bottom \wrapfigure{r}[\dimexpr \marginparwidth+\marginparsep]{\wd\marginbox} \raisebox{\dimexpr \dimen0-\intextsep-\ht\marginbox}[\dimexpr \dimen0-2\intextsep][0pt]{\usebox\marginbox}% \endwrapfigure \marginpar{\rule{0pt}{\dimen0}}% \fi} \makeatother

\begin{document}

\begin{marginfigurewide}{2\marginparwidth} \includegraphics[width=\linewidth]{example-image} \caption{Some caption.} \label{fig:somefig} \end{marginfigurewide}

Place note here.\sidenote{\LipsumPar{2}}

%\LipsumPar{1} \lipsum[1-2]

\begin{marginfigurewide}{2\marginparwidth} \includegraphics[width=\linewidth]{example-image} \caption{Some caption.} \label{fig:somefig} \end{marginfigurewide}

Place note here.\sidenote{\LipsumPar{2}}

\lipsum[3-4]

\end{document}

John Kormylo
  • 79,712
  • 3
  • 50
  • 120
  • Thank you, this works and is an environment, making it simple to use! But this has the same problem of my approach above. Here's what happens with a sidenote: https://imgur.com/a/8F6NRPS . I still can't find a way to flush the margin or reserve space there. – brunobg Sep 09 '20 at 16:09
  • If you change the 0pt to \marginparwidth in the \marginpar, you will see that the space SHOULD be occupied. OTOH, marginnotes (for example) overlaps anything, including itself. – John Kormylo Sep 09 '20 at 16:36
  • I found another solution meanwhile: just loading \use{marginfix} seems to automatically solve the issues. I suggest you patch your answer with this and I'll accept it. Thanks a lot! – brunobg Sep 09 '20 at 17:19
  • Your second example does not work as well. The height is smaller than expected, and text goes back to its normal length before it should. – brunobg Sep 09 '20 at 17:24
  • Yes, but the problem left is exactly that sidenotes in the text are not floated properly. – brunobg Sep 09 '20 at 18:12
  • I don't know why, but sometimes this works but doesn't take into account the height of the caption and sometimes does not work at all, apparently always caused by the \marginphantom expression. Manually setting it with a static height is a workaround. – brunobg Sep 10 '20 at 15:37
  • Any idea why if the figure is too down the page it affects the text margins of the next page? Anyway to clear and make sure it doesn't? – brunobg Oct 02 '20 at 22:59
  • 1
    Both wrapfigure and marginpar have problems with the end of the page. One can use \WFclear between paragraphs to stop wrpafigure from wrapping text. I might be able to do something about marginpar. – John Kormylo Oct 03 '20 at 16:27
  • The new code fixes the overflow, and with \wrapfigure{o} it works in symmetric pages too. Thank you. – brunobg Oct 09 '20 at 22:42
  • There's still something slightly wrong with dimen0, but I can't quite point to the error. If the image is very near the end of the page it affects the first line of the next page. Changing it to \pagegoal-\pagetotal-2\ht\strutbox\relax fixes it and I saw no other problems, but it's just a random correction factor. – brunobg Oct 21 '20 at 15:31
  • Oops. The contents of \marginpar are not expanded immediately, so \dimen0 could have been modified. Sorry about that. – John Kormylo Oct 21 '20 at 15:42