65

wrapfig is incompatible with the enumerate and itemize environments. Is there a typographical reason not to wrap a list around a figure or is it a technical limitation of LaTeX? If it is a technical limitation, is there any work (new packages or changes to LaTeX) currently being done to eliminate the limitation in the future?

Edit: To respond to some of the comments: I realize that there are "gymnastics" which can make this work. I do not have an example of the problem. Whenever I run into a problem with wrapfig because it is near an enumerate or itemize environment, I search for an easy solution, find none, and move the figure elsewhere. In the vast majority of cases, the cost of learning the complex solutions isn't worth the benefit of keeping the figure where I want it.

8
  • 5
    I have some thoughts for LaTeX3: currently we still need to do work on this, but I would expect 13galley to eventually cover this.
    – Joseph Wright
    Jun 8, 2012 at 19:04
  • 1
    Another solution to having cutouts in latex lists is given here tex.stackexchange.com/questions/53702/… Jun 8, 2012 at 20:45
  • 1
    @JosephWright Your first comment that 13galley would eventually help is from 2012. Is there any progress since then regarding the question? Or even better a production ready solution?
    – student
    Sep 10, 2015 at 21:37
  • 1
    @JosephWright What do you mean by "new format" in this case?
    – student
    Sep 11, 2015 at 6:28
  • 2
    @JosephWright I’m also curious about how this is progressing. I like to let text wrap around figures, and wrapfigure is far too inflexible for this purpose. My tests of xgalley were very promising until I realized it created wrong vertical spacing around lists. Is there any hope this can be fixed to make the package useful within LaTeX2e?
    – Gaussler
    May 12, 2016 at 8:48

5 Answers 5

26

FWIW, wrapfigure works out of the box in ConTeXt. So, it is clearly not a limitation of TeX.

\setuppapersize[A5]

\useexternalfigure[ctanlion][http://www.ctan.org/lion/ctan_lion_350x350.png][width=3cm]


\starttext

\placefigure[left,2*hang]{Test}
  {\externalfigure[ctanlion]}

\startitemize[n]
  \item \input ward
  \item \input ward
  \item \input ward
\stopitemize

\stoptext

which gives:

enter image description here

Removing 2*hang from \placefigure gives:

enter image description here

3
  • 5
    +1: This is a really nice example for ConTeXt's simplicity. May 22, 2015 at 13:54
  • What if I want to use a figure from a png file in the directory? Oct 26, 2021 at 19:45
  • @MarcoDisce: Just use \externalfigure[filename.png]. See using graphics on ConTeXt wiki for more details.
    – Aditya
    Oct 28, 2021 at 3:06
24

The cutwin package (and some \parshape gymnastics) can be used here:

\documentclass{article}
\usepackage{cutwin}
\usepackage{caption}
\usepackage{graphicx}
\usepackage{lipsum}

\begin{document}
\renewcommand\windowpagestuff{%
  \hspace*{25pt}\includegraphics[height=4cm]{ctanlion}
  \captionof{figure}{A test figure.}
}
\opencutleft

\begin{cutout}{2}{10pt}{0.5\linewidth}{12}
\begin{enumerate}
{%
\parshape 15 26pt \linewidth 26pt \linewidth 0.5\linewidth 0.5\linewidth
  0.5\linewidth 0.5\linewidth  0.5\linewidth 0.5\linewidth  0.5\linewidth 0.5\linewidth
  0.5\linewidth 0.5\linewidth   0.5\linewidth 0.5\linewidth   0.5\linewidth 0.5\linewidth 
  0.5\linewidth 0.5\linewidth   0.5\linewidth 0.5\linewidth   0.5\linewidth 0.5\linewidth
  0.5\linewidth 0.5\linewidth   0.5\linewidth 0.5\linewidth 26 pt \linewidth
\item \lipsum[1]
}%
\item \lipsum[2]
\item \lipsum[2]
\end{enumerate}
\end{cutout}

\end{document}

enter image description here

CTAN lion drawing by Duane Bibby.

9
  • 1
    This should even work if you want to put the picture at the start of the numbering. I didn't try it with cutwin, but just an ordinary \parshape.
    – Werner
    Jun 8, 2012 at 19:05
  • @Werner you're probably right; I used cutwin to put the figure after some lines of the numbering; right now I have to leave, but I will do some tests later and post some code if no one else has done it. Jun 8, 2012 at 19:09
  • If this is a good, general solution to the problem, would it be possible to develop a package which makes it possible to do this as few of lines of code as wrapfig? Could wrapfig be modified to use this alternative approach when used in a list?
    – ScottKu
    Jun 8, 2012 at 20:01
  • Your minimal working example (cut win package) fails if one uses a different font, say \usepackage{palatino}. Jun 9, 2012 at 3:18
  • 1
    what if you want to add two different figures inside the same itemize?
    – glS
    Dec 4, 2015 at 11:18
7

It is possible by putting the wrapfigure into a parbox or minipage as is mentioned in some of the duplicates of this question. However those methods usually fix vertical spacing issues by manually inserting \vspace with hand picked values. This solution works automatically by using a strut. The strut places the baseline of the first text line at a specified distance from the top of the minipage. Then adjustbox is used to place the top of the minipage exactly that amount above the outer baseline.

\documentclass{article}

\usepackage{calc}
\usepackage{adjustbox}
\usepackage{lipsum}
\usepackage{wrapfig}

\begin{document}

\newlength{\strutheight}
\settoheight{\strutheight}{\strut}
\begin{enumerate}
  \item \lipsum[1]
  \item
    \begin{adjustbox}{valign=T,raise=\strutheight,minipage={\linewidth}}
      \begin{wrapfigure}{l}{0pt}
        \includegraphics[width=3cm]{example-image-a}
      \end{wrapfigure}
    \strut{}\lipsum[2]
    \end{adjustbox}
\end{enumerate}

\end{document}
5

Here's a kluge. It replaces itemize with a lookalike, instead of trying to fiddle around with wrapfig.

\documentclass{article}

%put this code in preamble
\newlength{\bulletwidth}\settowidth{\bulletwidth}{$\bullet$}
\newcommand{\mitem}{\setlength{\leftskip}{\leftmargin}\hspace*{-\labelsep}\hspace*{-\bulletwidth}$\bullet$\hspace*{\labelsep}}
\newcommand{\mend}{\setlength{\leftskip}{0cm}}

\begin{document}

Some text.

\mitem This is an example of a list item.

\mitem Second item in list.

\mend

Some more text.

\end{document}

Each \mitem in the list must be preceded by a blank line. The list ends with \mend (also preceded by a blank line). There's no command to begin the list. This works for simple text items; I haven't tried it with anything more complicated.

Someone who knows more about how itemize works (and why it conflicts with wrapfig) might be able to make an even better imitation. It would also be fairly easy to generalize this to enumerate'd lists if necessary.

1
  • 1
    If each \mitem must start with a new paragraph, why not simply put a \par into its definition?
    – Skillmon
    May 15, 2019 at 19:39
1

You can create a new wrap enviroment. In the following MWE my wrapr env. places the image in the right side of the page while wrapl place it in the left. Both enviroments have the same structure:

wrapr{vertical adjustment of text}{number of lines}{horizontal space needed for the image}{vertical adjustment of image}{IMAGE}{TEXT}

We can see here both enviroments in use

\documentclass[a4paper,11pt]{article}
\usepackage{graphicx}
\usepackage{tikz,pgfplots,tkz-euclide}
\tkzSetUpPoint[size=7,fill=white]
\usepackage{wrapfig}


\newenvironment{WrapText1}[3][r]
{\wrapfigure[#2]{#1}{#3}}
{\endwrapfigure}
\newenvironment{WrapText2}[3][l]
{\wrapfigure[#2]{#1}{#3}}
{\endwrapfigure}
\newcommand{\wrapr}[6]{
\begin{minipage}{\linewidth}\mbox{}\\
\vspace{#1}
\begin{WrapText1}{#2}{#3}
\vspace{#4}#5\end{WrapText1}#6
\end{minipage}}

\newcommand{\wrapl}[6]{
\begin{minipage}{\linewidth}\mbox{}\\
\vspace{#1}
\begin{WrapText2}{#2}{#3}
\vspace{#4}#5\end{WrapText2}#6
\end{minipage}}
\usepackage{lipsum}


\begin{document}
\wrapr{-4mm}{8}{4cm}{5mm}{\begin{tikzpicture}
\tkzDefPoint(3,0){C}
\tkzDefPoint(0,0){B}
\tkzDefPoint(1,2){A}
\tkzDefPoint(1.33,.66){G}
\tkzDefPoint(1.5,0){M}
\tkzDefPoint(.5,1){N}
\tkzDefPoint(2,1){P}
\draw(A)--(B)--(C)-- cycle;
\draw(A)--(M);
\draw(B)--(P);
\draw(C)--(N);
\tkzLabelPoint[left](B){$B$}
\tkzLabelPoint[below](M){$D$}
\tkzLabelPoint[right](P){$E$}
\tkzLabelPoint[left](N){$Z$}
\tkzLabelPoint[right](C){$C$}
\tkzLabelPoint[above](A){$A$}
\tkzLabelPoint[left,yshift=-3mm,xshift=1.7mm](G){$G$}
\tkzDrawPoints(A,B,C,M,N,P,G)
\end{tikzpicture}}{\begin{enumerate}
\item \lipsum[1]
\end{enumerate}}
\vspace{2cm}
\wrapl{-4mm}{8}{3cm}{5mm}{\begin{tikzpicture}
\tkzDefPoint(3,0){C}
\tkzDefPoint(0,0){B}
\tkzDefPoint(1,2){A}
\tkzDefPoint(1.33,.66){G}
\tkzDefPoint(1.5,0){M}
\tkzDefPoint(.5,1){N}
\tkzDefPoint(2,1){P}
\draw(A)--(B)--(C)-- cycle;
\draw(A)--(M);
\draw(B)--(P);
\draw(C)--(N);
\tkzLabelPoint[left](B){$B$}
\tkzLabelPoint[below](M){$D$}
\tkzLabelPoint[right](P){$E$}
\tkzLabelPoint[left](N){$Z$}
\tkzLabelPoint[right](C){$C$}
\tkzLabelPoint[above](A){$A$}
\tkzLabelPoint[left,yshift=-3mm,xshift=1.7mm](G){$G$}
\tkzDrawPoints(A,B,C,M,N,P,G)
\end{tikzpicture}}{\begin{enumerate}
\item \lipsum[1]
\end{enumerate}}
\end{document}

enter image description here

You must log in to answer this question.

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