Since there is no \tikz
answer I thought I felt obligated to provide one:
- To keep my reputation for the overkill solution. :-)
- But seriously, I interpreted that the goal of this question was to draw attention to a particular item in a list.
Adding a parenthesis is not the only way to highlight an \item
in a list, and by using the infamous \tikzmark
many other options are possible. Below I have used the term marker to refer to the the elements that are used to draw attention to a list member.
Basic:
To use the technique defined here, all you need to do is to use \SpecialItem
instead of the usual \item
in the list. This will by default make a call to \DrawParen
which adds a parenthesis at the start and end of the list item as shown here:
\begin{enumerate}
\SpecialItem Default behaviour of \verb|\SpecialItem.|
\SpecialItem \verb|\SpecialItem| with longer text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit
\end{enumerate}
As requested by Jake, there is no need to specify where the end parenthesis is placed. This is determined automatically based on where the text of the \item
terminates. So, the code above generates (with the preamble used in the MWE below):

There is a question as to what to do when the text takes up more than one line, as in the second case above. To handle this case, I have defined a starred variant, \DrawParen*
which takes into account the height of the lines of text and the parenthesis are re-sized appropriately:
To facilitate the use of different drawing macros, \SpecialItem
accepts an optional first parameter to specify the macro that is to be used to do the actual drawing. This defaults to \DrawParen
, so to use the starred variant we need to use \SpecialItem[\DrawParen*]
.
So, the code:
\begin{enumerate}
\SpecialItem[\DrawParen*] \verb|\SpecialItem[\DrawParen*]| with longer text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit
\end{enumerate}
yields:

Now the parenthesis are high enough to enclose the multiple lines and the right one is placed on the right side.
Extended:
The above was the basic usage, but you can define your own drawing macros.
Below, I have defined several drawing macros.
\SpecialItem[\DrawAsterix]
:

Since there is no marker on the right hand side, \DrawAsterix
and \DrawAsterix*
are identical.
\SpecialItem[\DrawBrace]
:

\SpecialItem[\DrawBracket]
:
Similar to \DrawBrace
, but draws a square bracket.
\SpecialItem[\DrawBox]
:

Note that it does not make sense to use \DrawBox
(the un-starred variant) when the text requires multiple lines.
\SpecialItem[\DrawShadedBox]
:

Custom Markers:
If the drawing options defined here are not enough, you can define your own and pass this macro to \SpecialItem
. Any custom drawing macro would need to be defined with arg specs {s O{} m m}
, where I have used the format from the xparse
package.
The parameters to this custom drawing macro are:
* starred variant sets the markers at the end of the line on the right
#2 = optional drawing parameter.
This is actually not used in the code as of yet, at least not fully
used for its intended purpose.
#3 = name of `\tikzmark` that defines the location of the start of this `\item`,
#4 = name of `\tikzmark` that defines the location of the end of this `\item`.
So, assuming you want to stick with the xparse
package, then \MyCustomDrawMacro
would look like:
\NewDocumentCommand{\MyCustomDrawMacro}{s O{} m m}{%
\begin{tikzpicture}[overlay, remember picture]
\IfBooleanTF{#1}{%
... draw for starred variant ...
}{%
... draw for un-starred variant ...
}%
\end{tikzpicture}%
}%
Then to use this you would provide this as the first optional parameter to \SpecialItem
:
\SpecialItem[\MyCustomDrawMacro] ...text of item here...
Nested Usage:
Although not all combinations produce good results, it is now possible to have nested usage:

and even further nesting:

It should be noted that for nested usage there needs to be indenting on the right hand side so that the markers don't all overlap. To achieve this I used the enumitem
package:
\setlist{before=\setlength{\rightmargin}{\leftmargin}}
Notes:
This does require two runs: the first to compute the positions of the drawing, 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.
Even though I used the the xparse
package, this could certainly be done without this additional package if so desired.
I have used newtoggle
from the etoolbox
package as I prefer that syntax versus the \newif
syntax. But if you don't want to include an additional package it should be pretty straightforward to adapt this to use \newif
or some other conditional methods.
It should be noted that in this answer to strange interaction between mdframed
and item, egreg mentions that
Redefining \item
can be dangerous and have impredictable results
which is exactly what I have done here, so perhaps an alternate solution might be needed if this fails under certain circumstances.
References:
Known Issues:
- Although the nested usage works as shown there is something that is nto getting properly reset after nested usage that affects the non-nested usage. In the MWE below I have commented out the test cases for the nested usage so that it produces useable results. However, if you un-comment the nested usage test cases you will notice that the subsequent usage is really messed up. Will look into this and try to post an update
Further Enhancements:
The use of \DrawBox
without the * does not make sense for the case where the text is longer than one line. One could automate a test for this and automatically revert to \DrawBox*
if the content was longer than one line. This should not be too difficult.
The drawing for \DrawParen
using bend left
can result in a large bracket if the text is over many lines. Perhaps some logic here to limit the amount of bending to some maximum?
There is a slight issue when you try to fill the text with a color in that the text is not placed via \tikz
so that a low fill opacity
needs to be used.
To fix this issue, perhaps get \tikz
to place the text and hence one could specify text opacity=1.0
so that a darker fill could be used.
The left brace is currently to the right of the margin, and the right brace (with the * variant is past the right margin. So perhaps some tweaking here is needed if that is a problem. Need to decide if both the drawing should just be on the margin, of if you want the drawing within the margin, then need to reduce the line width to which the text can flow.
Tweaks needed for placement of the markers in nested usage.
The current version requires that a new \Draw...
macro be defined if you want to change any of the tikz settings. For instance \DrawShadedBox
is really the same as \DrawBox[Shaded Box Style]...
, but I do not know of a way to pass in optional parameters along with the macro name (but without passing the mandatory parameters as they are only known later).
Caveat:
This section can safely be ignored, and is ONLY relevant in case one tries to compare this to the earlier solution at Box around a few items in an itemize environment. Otherwise, please ignore this section as it will only result in confusion -- it certainly confused me and I wrote the other solution!!
Ok, since you are choosing to read on: The earlier solution accommodated boxing the content with either the label included or not included. In the earlier solution, there is \DrawBox
, which does not include the label and \DrawBoxWide
which does include the label in the box. In this solution I have decided to not provide the case where the label is not boxed. So, what this all means is that \DrawBox
in this earlier solution does not have a corresponding macro here, and that the \DrawBoxWide
from the earlier solution corresponds to \DrawBox
in this solution.
If this section does not make sense, please ignore it -- it will help me in the future should I need to come back and make sense of these two solutions.
Code:
\documentclass{article}
\usepackage{etoolbox}% \newtoggle (conditional processing)
\usepackage{letltxmacro}% Duplicate definitions of existing macros
\usepackage{xparse}% \NewDocumentCommand and \RenewDocumentCommand
\usepackage{xstring}% \IfEq
\usepackage{enumitem}%
\usepackage{tikz}%
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathreplacing}
%\usepackage{showframe}%
\newcommand{\Text}{% Dummy text for testing purposes
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed accumsan nulla ac ipsum elementum interdum.
}%
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture] \node (#1) {};}
% -------------------------------------------------- Drawing Settings
\newcommand*{\RightTweak}{0.2em,-0.3em}%
\newcommand*{\LeftTweak}{-\labelwidth,0.9em}%
\newcommand*{\BraceAmplitude}{0.25em}%
% -------------------------------------------------- Drawing Macros
\tikzset{Box Style/.style={draw=red}}%
\NewDocumentCommand{\DrawBox}{%
s % * = box drawn to full line width
O{}% #2 = optional tikz draw/fill paramaters
m % #3 = name of left \tikzmark
m % #4 = name of right \tikzmark
}{%
%
\tikz[overlay,remember picture]{%
\IfBooleanTF{#1}{%
\coordinate (SWPoint) at ($(#3 |- #4)+(\linewidth,0)$);
}{%
\coordinate (SWPoint) at (#4);
}%
\draw[Box Style, #2] ($(#3)+(\LeftTweak)$) rectangle ($(SWPoint)+(\RightTweak)$);}
}%
\tikzset{Shaded Box Style/.style={thick, draw=violet, fill=yellow!20, fill opacity=0.1}}%
\NewDocumentCommand{\DrawShadedBox}{%
s % * = box drawn to full line width
O{}% #2 = optional tikz draw/fill paramaters
m % #3 = name of left \tikzmark
m % #4 = name of right \tikzmark
}{%
%
% Note that the fill opacity needs to be quite small as this fill
% is done on top of the text (which was not placed here via tikz.
\IfBooleanTF{#1}{%
\DrawBox*[Shaded Box Style, #2]{#3}{#4}%
}{%
\DrawBox[Shaded Box Style, #2]{#3}{#4}%
}%
}%
% To properly place the left brace, paren, bracket, this needs tweaking
\newcommand*{\LeftTweakBrackets}{\labelwidth}%
% This is shared with the bracket/paren drawing macros
\NewDocumentCommand{\ComputeCoordinates}{%
s%
O{}% #2 = Unused here -- makes the #3, #4 compatible with macros below
m% #3 = name of left \tikzmark
m% #4 = name of right \tikzmark
}{%
\IfBooleanTF{#1}{%
\coordinate (NEPoint) at ($(#3.north)+(-\LeftTweakBrackets, 0.5*\baselineskip)$);
\coordinate (SEPoint) at ($(#3 |- #4)+(-\LeftTweakBrackets,-0.5*\baselineskip)$);
%
\coordinate (NWPoint) at ($(#3.north)+(\linewidth, 0.5*\baselineskip)$);
\coordinate (SWPoint) at ($(#3 |- #4)+(\linewidth,-0.5*\baselineskip)$);
}{%
\coordinate (NEPoint) at ($(#3.north)+(-\LeftTweakBrackets, 0.5*\baselineskip)$);
\coordinate (SEPoint) at ($(#3) +(-\LeftTweakBrackets,-0.5*\baselineskip)$);
%
\coordinate (NWPoint) at ($(#4.north)+(0, 0.5*\baselineskip)$);
\coordinate (SWPoint) at ($(#4) +(0,-0.5*\baselineskip)$);
}%
}%
\tikzset{Brace Style/.style={
decoration={brace,amplitude=\BraceAmplitude}, decorate,
ultra thick, blue
}%
}%
\NewDocumentCommand{\DrawBrace}{%
s % * = draw to full line width
O{}% #2 = optional tikz draw/fill paramaters
m % #3 = name of left \tikzmark
m % #4 = name of right \tikzmark
}{%
\begin{tikzpicture}[overlay, remember picture]
\IfBooleanTF{#1}{%
\ComputeCoordinates*{#3}{#4}%
}{%
\ComputeCoordinates{#3}{#4}%
}%
\draw [Brace Style, #2] (SEPoint) -- (NEPoint);
\draw [Brace Style, #2] (NWPoint) -- (SWPoint);
\end{tikzpicture}%
}%
% https://tex.stackexchange.com/questions/55068/is-there-a-tikz-equivalent-to-the-pstricks-ncbar-command
\tikzset{
ncbar/.style={% easy way to get sqaure brackets
to path=(\tikztostart)
-- ($(\tikztostart)!#1!90:(\tikztotarget)$)
-- ($(\tikztotarget)!#1!-90:(\tikztostart)$)
-- (\tikztotarget)
},
ncbar/.default=0.5cm
}
\tikzset{Bracket Style/.style={ultra thick, brown}}%
\NewDocumentCommand{\DrawBracket}{s O{} m m}{%
\begin{tikzpicture}[overlay, remember picture]
\IfBooleanTF{#1}{%
\ComputeCoordinates*{#3}{#4}%
}{%
\ComputeCoordinates{#3}{#4}%
}%
\draw [Bracket Style, #2] (SEPoint) to [ncbar=\BraceAmplitude] (NEPoint);
\draw [Bracket Style, #2] (NWPoint) to [ncbar=\BraceAmplitude] (SWPoint);
\end{tikzpicture}%
}%
\tikzset{Paren Style/.style={ultra thick, red}}%
\NewDocumentCommand{\DrawParen}{s O{} m m}{%
\begin{tikzpicture}[overlay, remember picture]
\IfBooleanTF{#1}{%
\ComputeCoordinates*{#3}{#4}%
}{%
\ComputeCoordinates{#3}{#4}%
}%
\draw [Paren Style, #2] (SEPoint) to [bend left] (NEPoint);
\draw [Paren Style, #2] (NWPoint) to [bend left] (SWPoint);
\end{tikzpicture}%
}%
\tikzset{Asterix Style/.style={text=red}}%
\NewDocumentCommand{\DrawAsterix}{s O{} m m}{%
\begin{tikzpicture}[overlay, remember picture]
\IfBooleanTF{#1}{%
\ComputeCoordinates*{#3}{#4}%
}{%
\ComputeCoordinates{#3}{#4}%
}%
\node [Asterix Style, #2] at ($(SEPoint)!0.5!(NEPoint)$) {\Huge$\ast$};
\end{tikzpicture}%
}%
% -------------------------------------------------- Non-Drawing Macros
% This toggle is set when we are within a "\SpecialItem" so that we
% can do the appropriate drawing when we get to the end of this item.
% To allow for nesting we need one of these for each nesting depth
% So, to allow for more levels of nesting declare more of these.
\newtoggle{InSpecialItem1}\togglefalse{InSpecialItem1}%
\newtoggle{InSpecialItem2}\togglefalse{InSpecialItem2}%
\newtoggle{InSpecialItem3}\togglefalse{InSpecialItem3}%
\newtoggle{InSpecialItem4}\togglefalse{InSpecialItem4}%
% To allow for nesting we need to use different names for the tikzmarks,
% and the toggles (defined above). So we use the vallue of this counter
% to name those. This counted is incremented at the \begin{enumerate} and
% decremented at \end{enumerate}
\newcounter{EnumerateDepth}%
\makeatletter
% https://tex.stackexchange.com/questions/20655/how-to-undo-a-def-i-e-need-a-undef-capability
\newcommand*\ResetToUndefined[1]{\expandafter\gdef\csname#1\endcsname{\@undefined}}%
\makeatother
\newcommand*{\EndTikzMarkAndDrawIfNeeded}{%
\iftoggle{InSpecialItem\arabic{EnumerateDepth}}{%
% We have reached the end of a \SpecialItem, which could be
% either due to a subsequent \item, a subsequent \SpecialItem,
% to an end{enumerate}.
\global\togglefalse{InSpecialItem\arabic{EnumerateDepth}}%
\ifcsname MarkEnd\Alph{EnumerateDepth}\endcsname%
% The location of the end \tikzmark was already marked,
% which would be the case if we were coming out of a nested
% \end{enumerate}).
%
% We need to clear this defintion so that it can be used
% again if needed:
\ResetToUndefined{MarkEnd\Alph{EnumerateDepth}}%
\else%
% The location of the end \tikzmark was not already marked
% Hence, we need to mark this current point as the end
% \tikzmark location.
\tikzmark{MarkEnd\Alph{EnumerateDepth}}%
\fi%
% -----------------------------------------------------------
% Draw whatever was specified to be drawn by \SpecialItem
% and draw whatever was specified to be drawn by \SpecialItem
\SpecialItemStyle[thick]%
{MarkStart\Alph{EnumerateDepth}}%
{MarkEnd\Alph{EnumerateDepth}}%
}{}%
}%
% To be able to handle nested use of \SpecialItem we need to know
% what enumerate depth we are at, so we increment that counter at
% every \begin{enumerate}. Hence first level has count=1.
\LetLtxMacro\OriginalEnumerate{\enumerate}%
\renewcommand*{\enumerate}{%
\addtocounter{EnumerateDepth}{1}% Increase enumerate nesting depth
\OriginalEnumerate%
}%
% Special Case: If we are ending a nested enumerarte, but the last item
% in the parent list is a SpecialItem we need to close those as well.
\newcounter{NestingDepthCounter}
\newcommand*{\EndAnyParentTikzMarks}{%
\edef\NestingDepth{\arabic{EnumerateDepth}}%
\IfStrEq{\NestingDepth}{0}{}{%
\foreach \x in {1,...,\NestingDepth} {%
\setcounter{NestingDepthCounter}{\x}%
\iftoggle{InSpecialItem\arabic{NestingDepthCounter}}{%
% Note that we do NOT togglefalse{InSpecialItem\x} here as
% the drawing needs to be done we come out of this enumerate
% so that the line widths are correct, and that the correct
% drawing macro is used for that enumerated depth.
%% \global\togglefalse{InSpecialItem\x}% No!! Not for this special case!
\ifcsname MarkEnd\Alph{EnumerateDepth}\endcsname%
% The location of the end \tikzmark was already marked,
% which would be the case if we were coming out of a nested
% \end{enumerate}). So don't mark it again.
\else%
\tikzmark{MarkEnd\Alph{NestingDepthCounter}}%
%
% So that we know that we have already marked an end for this
% \tikzmark and don't overwrite the current location.
% If there is a way to check if a \tikzmark is already defined
% then this \gdef here could be elimianted.
\expandafter\gdef\csname MarkEnd\Alph{NestingDepthCounter}\endcsname{}%
\fi%
}{}%
}%
}%
}%
% If last \item was a special \tikzmark, then at the end of
% enumerate we need to add the other end of the \tikzmark,
% and do the appropriate drawing.
\let\OriginalEndEnumerate\endenumerate%
\renewcommand*{\endenumerate}{%
\EndTikzMarkAndDrawIfNeeded%
%
\EndAnyParentTikzMarks%
\addtocounter{EnumerateDepth}{-1}% Decrease enumerate nesting depth
%
\OriginalEndEnumerate% end the enumerate
}%
% If previous \item was a special \tikzmark, then at the
% subsequent \item we need to add the other end of the
% \tikzmark, and do the appropriate drawing
\LetLtxMacro\OriginalItem{\item}%
\RenewDocumentCommand{\item}{o}{%
\EndTikzMarkAndDrawIfNeeded%
\IfNoValueTF{#1}{%
\OriginalItem% start the usual item
}{%
\OriginalItem[#1]% start the usual item with given label
}%
}%
\NewDocumentCommand{\SpecialItemStyle}{O{} m m}{}%
\NewDocumentCommand{\SpecialItem}{%
O{\DrawParen}% #1 = highlighting type
o% #2 = optional paramater to \item
}{%
\EndTikzMarkAndDrawIfNeeded% In case previous item was also a \SpecialItem
% --------------------------------------------------
% Redefine how this particular special item is to be marked when it ends.
\RenewDocumentCommand{\SpecialItemStyle}{O{} m m}{#1[##1]{##2}{##3}}%
% --------------------------------------------------
\global\toggletrue{InSpecialItem\arabic{EnumerateDepth}}%
\IfNoValueTF{#2}{%
\OriginalItem% start a special item
}{%
\OriginalItem[#2]% start a special item with given label
}%
\tikzmark{MarkStart\Alph{EnumerateDepth}}%
\ignorespaces% As per https://tex.stackexchange.com/questions/73434
}%
\setlist{before=\setlength{\rightmargin}{\leftmargin}}
\begin{document}
\begin{enumerate}
\item Normal Item
\item[A.] Normal Item with custon label [A.]
\SpecialItem \verb|\DrawParen|
\SpecialItem \verb|\DrawParen| \Text
\SpecialItem[\DrawParen*] \verb|\DrawParen*|
\SpecialItem[\DrawParen*] \verb|\DrawParen*| \Text
\SpecialItem[\DrawAsterix] \verb|\DrawAsterix|
\SpecialItem[\DrawBrace] \verb|DrawBrace|
\SpecialItem[\DrawBrace*] \verb|DrawBrace*|
\item A normal item in between special items
\SpecialItem[\DrawBrace] DrawBrace with text: \Text
\SpecialItem[\DrawBrace*] DrawBrace* with text: \Text
\SpecialItem[\DrawBracket] DrawBracket with text: \Text
\SpecialItem[\DrawBracket*] DrawBracket* with text: \Text
\SpecialItem[\DrawBox] DrawBox Item
\SpecialItem[\DrawBox*] DrawBox*
\SpecialItem[\DrawBox] DrawBox with text - Does not make sense.
\SpecialItem[\DrawBox*] DrawBox with text: \Text
\SpecialItem[\DrawShadedBox][B.] DrawShaded box with custom label [B.]
\SpecialItem[\DrawShadedBox*] DrawShaded box with text: \Text
\end{enumerate}
%\newpage
%Check nesting:
%\begin{enumerate}
% \SpecialItem[\DrawBrace] \verb|\DrawBrace| of parent with nested list
% \begin{enumerate}
% \SpecialItem[\DrawBracket] \verb|\DrawBracket| nested in above list
% \end{enumerate}
% %
% \SpecialItem[\DrawBrace*] \verb|\DrawBrace*| of parent with nested list: \Text
% \begin{enumerate}
% \SpecialItem[\DrawBracket*] \verb|\DrawBracket*| nested in above list: \Text
% \end{enumerate}
% %
% \SpecialItem[\DrawBracket*] \verb|\DrawBracket*| of parent with nested list
% \begin{enumerate}
% \SpecialItem[\DrawBrace*] \verb|\DrawBrace*| nested in above list
% \begin{enumerate}
% \SpecialItem[\DrawBox*] \verb|\DrawBox*| nested in above list
% \begin{enumerate}
% \SpecialItem[\DrawParen] \verb|\DrawParen| nested in above list \Text
% \item Regular item
% \end{enumerate}
% \end{enumerate}
% \end{enumerate}
%\end{enumerate}
\newpage
Test cases given in description:
\begin{enumerate}
\SpecialItem Default behaviour of \verb|\SpecialItem.|
\SpecialItem \verb|\SpecialItem| with longer text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit
\end{enumerate}
\begin{enumerate}
\SpecialItem[\DrawParen*] \verb|\SpecialItem[\DrawParen*]| with longer text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit
\end{enumerate}
\begin{enumerate}
\SpecialItem[\DrawAsterix] \verb|\SpecialItem[\DrawAsterix]| with longer text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit
\end{enumerate}
\begin{enumerate}
\SpecialItem[\DrawBrace] \verb|\SpecialItem[\DrawBrace]| with short text.
\SpecialItem[\DrawBrace] \verb|\SpecialItem[\DrawBrace]| with longer text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit
\SpecialItem[\DrawBrace*] \verb|\SpecialItem[\DrawBrace*]| with longer text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit
\end{enumerate}
\begin{enumerate}
\SpecialItem[\DrawBox] \verb|\SpecialItem[\DrawBox]| with short text.
\SpecialItem[\DrawBox*] \verb|\SpecialItem[\DrawBox*]| with longer text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit
\end{enumerate}
\begin{enumerate}
\SpecialItem[\DrawShadedBox] \verb|\SpecialItem[\DrawShadedBox]| with short text.
\SpecialItem[\DrawShadedBox*] \verb|\SpecialItem[\DrawShadedBox*]| with longer text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit
\end{enumerate}
\end{document}
\startitem ... \stopitem
approach is better (it's only optional in ConTeXt, but is required for some mechanisms to work).