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'm using beamer and want to call out a few items in a list by drawing a box around them, and, ideally, having a small comment appear next to the box, like this:

enter image description here

share|improve this question
    
Related (but different) question: Replace \item with \MyItem to box each list member with an mdframe –  Peter Grill May 18 '12 at 20:54
add comment

migrated from stackoverflow.com Feb 26 '12 at 23:59

This question came from our site for professional and enthusiast programmers.

1 Answer

up vote 21 down vote accepted

One way to do that is to adapt the code from Highlight elements in the matrix. Below, I provide two macros \DrawBox and \DrawBoxWide depending on if you want to include the list markers or not. The default below is to produce a red box, but this can be adjusted to suit, or the options can be specified on a per use basis (as in the second example):

enter image description here

However, since the width of the box is based on the width of the last item, there is a possibility that the box won't be wide enough if the last item is shorter than the wides item within the box. For this case I have defined \DrawBox* and \DrawBoxWide* which use enclose the items in a box as wide as the line:

enter image description here

Note that in the above the width of the box is the full \linewidth. This is not an issue if the text uses the full width as is the case of the blue box above, but for the case where the text is not the full width (as is the case for the red box), one might desire a tight box around the text. In this case I would recommend that the last line be set in a box as wide as the widest text using:

\makebox[\widthof{\WidestText}][l]{<text>}\tikzmark{right}

which yields:

enter image description here

Syntax:

To use this you place \tikzmark{left} to mark the position where the top left of the box is, and \tikzmark{right} to mark the position of the bottom right of the box. After these two positions have been marked you call the \DrawBox or \DrawBoxWide (or the starred variant) macros to draw the box.

Notes:

  • This does require two runs: the first to compute the positions of the box, and the second to draw it in the correct spot.
  • Since this is using tikz, you automatically get all the flexibility inherent in tikz, such as line styles, line thickness, line color, fill, etc. These can be passed to the \DrawBox macros to customize each instance or provided as default options to maintain consistency.

Code:

\documentclass{article}
\usepackage{xparse}%  For \NewDocumentCommand
\usepackage{calc}%    For the \widthof macro
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\Text}{Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
    Sed accumsan nulla ac ipsum elementum interdum. }

\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture] \node (#1) {};}

\makeatletter
\NewDocumentCommand{\DrawBox}{s O{}}{%
    \tikz[overlay,remember picture]{
    \IfBooleanTF{#1}{%
        \coordinate (RightPoint) at ($(left |- right)+(\linewidth-\labelsep-\labelwidth,0.0)$);
    }{%
        \coordinate (RightPoint) at (right.east);
    }%
    \draw[red,#2]
      ($(left)+(-0.2em,0.9em)$) rectangle
      ($(RightPoint)+(0.2em,-0.3em)$);}
}

\NewDocumentCommand{\DrawBoxWide}{s O{}}{%
    \tikz[overlay,remember picture]{
    \IfBooleanTF{#1}{%
        \coordinate (RightPoint) at ($(left |- right)+(\linewidth-\labelsep-\labelwidth,0.0)$);
    }{%
        \coordinate (RightPoint) at (right.east);
    }%
    \draw[red,#2]
      ($(left)+(-\labelwidth,0.9em)$) rectangle
      ($(RightPoint)+(0.2em,-0.3em)$);}
}
\makeatother

\begin{document}
Using the \verb|\DrawBox and \DrawBoxWide|:
\medskip\par\noindent
\begin{minipage}{0.4\linewidth}
  \begin{enumerate}
        \item First Item
        \item \tikzmark{left}Second Item
        \item Third Item
        \item Fourth Item\tikzmark{right}
        \item Fifth Item
  \end{enumerate}
    \DrawBox[thick]
\end{minipage}
%
\begin{minipage}{0.4\linewidth}
  \begin{enumerate}
        \item First Item
        \item \tikzmark{left}Second Item
        \item Third item
        \item Fourth Item\tikzmark{right}
        \item Fifth Item
  \end{enumerate}
    \DrawBoxWide[thick, blue, fill=yellow, fill opacity=0.2]
\end{minipage}

Using the \verb|\DrawBox* and \DrawBoxWide*|:
\medskip\par\noindent
\begin{minipage}{0.4\linewidth}
  \begin{enumerate}
        \item First Item
        \item \tikzmark{left}Second Item
        \item Third item.
        \item Fourth Item\tikzmark{right}
        \item Fifth Item
  \end{enumerate}
    \DrawBox*[thick]
\end{minipage}
%
\begin{minipage}{0.4\linewidth}
  \begin{enumerate}
        \item First Item
        \item \tikzmark{left}Second Item
        \item Third item: \Text
        \item Fourth Item\tikzmark{right}
        \item Fifth Item
  \end{enumerate}
    \DrawBoxWide*[thick, blue, fill=yellow, fill opacity=0.2]
\end{minipage}

\noindent
For the case where the last line is not the longest and the lines before do not use the full width of the text, as would be the case below with \verb|\DrawBoxWide*|, you can use \verb|\makebox{\widthof{<widest_text>}{<text>}|

\newcommand*{\WidestText}{Third item which is wider}%
\begin{enumerate}
    \item First Item
    \item \tikzmark{left}Second Item
    \item Third item which is wider
    \item \makebox[\widthof{\WidestText}][l]{Fourth Item}\tikzmark{right}
    \item Fifth Item
\end{enumerate}
\DrawBoxWide[thick, brown]
\end{document}
share|improve this answer
    
Many thanks! This is exactly what I was looking for. –  user1234416 Feb 29 '12 at 3:37
    
Awesome solution! Just one note, it does not interact well with tikzexternalize. Take a look at this to disable tikzexternalize inside \tikzmark and \DrawBox. –  user1202136 Sep 17 '13 at 11:55
add comment

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.