# Beamer overlay box around text - the correct way?

I have something that "works," but I'm wondering if there's a more elegant solution. I want to box some text after an itemize in beamer, so this is what I'm doing:

\documentclass{beamer}

\begin{document}

\begin{frame}
\begin{itemize}[<+->]
\item Software-as-a-Service?
\item Platform-as-a-Service?
\item \only<-4>{Infrastructure-as-a-Service}\only<5->{\fcolorbox{red}{white}{Infrastructure-as-a-Service}}?
\item Other-stuff-as-a-Service?
\end{itemize}
\end{frame}

\end{document}


I get the effect that I want (with some added space on the boxed slide, which is not ideal), but I'm wondering if there's a more natural way to do this? I tried searching online and the trusty texdoc beamer, but maybe I'm looking in all the wrong places.

I also tried:

\item \fcolorbox<beamer:6>{red}{white}{Infrastructure-as-a-Service}?


but that left me with a black box until the red one was highlighted

-
It's not clear to me why are you using \only<-2>{Infrastructure-as-a-Service}. All you want is to have a boxed item to appear on frames 3 onwards? –  Gonzalo Medina Apr 5 '13 at 16:14
Perhaps the behaviour desired is the one addressed in Highlighting in beamer using TikZ nodes? –  Claudio Fiandrino Apr 5 '13 at 16:41
Yes, the effect is the same as in the other post. I was looking to have something boxed afterwards, I noticed that there's a typo in my original so I've edited the MWE accordingly –  zje Apr 5 '13 at 19:09

You could use the tried and tested tikzmark idea

Code

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{calc}

% tikzmark command, for shading over items
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture] \node (#1) {};}
\begin{document}
\begin{frame}

\begin{itemize}[<+->]
\item Software-as-a-Service?
\item Platform-as-a-Service?
\item \tikzmark{infrastructure}{Infrastructure-as-a-Service}
\item Other-stuff-as-a-Service?
\end{itemize}

\pause\tikz[overlay,remember picture]{\draw[draw=red,thick,double,fill opacity=0.2] ($(infrastructure)+(-0.5,0.4)$) rectangle ($(infrastructure)+(6,-0.2)$);}
\end{frame}
\end{document}

-
Got it, that's exactly the functionality I was looking for! Any idea why it pauses twice on the last item in the list? I tried stopping it from doing that by moving around the \pause, but I haven't been successful. –  zje Apr 5 '13 at 19:20
@zestrada remove the \pause command and use \tikz[overlay,remember picture]{\draw<+->[draw=red,thick,double,fill opacity=0.2] ($(infrastructure)+(-0.5,0.4)$) rectangle ($(infrastructure)+(6,-0.2)$);} instead. –  Gonzalo Medina Apr 5 '13 at 19:46
Cool, thanks! Didn't even think to try <+->! –  zje Apr 5 '13 at 23:12

A different approach could be to exploit the styles defined in Highlighting in beamer using TikZ nodes.

The code:

\documentclass{beamer}
\usepackage{lmodern}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{xparse}

\tikzset{
invisible/.style={opacity=0,text opacity=0},
visible on/.style={alt=#1{}{invisible}},
alt/.code args={<#1>#2#3}{%
\alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}}
},
}

\tikzset{
background fill/.style={fill=#1},
background fill/.default={white},
fill on/.style={alt=#1{}{background fill}},
}

\tikzset{
background draw/.style={draw=#1},
background draw/.default={white},
draw on/.style={alt=#1{}{background draw}},
}

\tikzset{
background filldraw/.style args={#1 filled by #2}{draw=#1, fill=#2},
background filldraw/.default=white filled by white,
filldraw on/.style={alt=#1{}{background filldraw}},
}

\tikzset{highlighting/.style={
append after command={
\pgfextra{
\path[rounded corners,
background draw=red,
draw on=<#1>,
overlay] ($(\tikzlastnode.south west)+(-0.015,-0.1)$) % to have some offset
rectangle ($(\tikzlastnode.north east)+(0.015,0.065)$);
}
}
}
}

\NewDocumentCommand{\highlight}{r<> m}{%
\tikz[baseline=(A.base)]
\node[highlighting=#1,
inner sep=0pt] (A) {#2};%
}

\begin{document}

\begin{frame}{Itemize with styles}
\begin{itemize}[<+->]
\item Software-as-a-Service?
\item Platform-as-a-Service?
\item \highlight<5>{Infrastructure-as-a-Service}?
\item Other-stuff-as-a-Service?
\end{itemize}
\end{frame}

\end{document}


The result:

Notes on the code

The TikZ node created does not occupy to much space due to the option inner sep=0pt, but since its dimensions are very tight around the text, the highlighting box created adds some space around (via offsets created thanks to the calc library). In order to avoid that this extra space may corrupts the alignment, the overlay option has been introduced to the highlighting path.

Now, without changing anything inside the document, it is possible to obtain different effects by selecting the different styles:

\tikzset{highlighting/.style={
append after command={
\pgfextra{
\path[rounded corners,
background fill=red!30, % filling
fill on=<#1>, % filling overlay specification
overlay] ($(\tikzlastnode.south west)+(-0.015,-0.1)$) % to have some offset
rectangle ($(\tikzlastnode.north east)+(0.015,0.065)$);
}
}
}
}


gives:

while:

\tikzset{highlighting/.style={
append after command={
\pgfextra{
\path[rounded corners,
background filldraw=red filled by red!30, % border+filling
filldraw on=<#1>, % overlay specification
overlay] ($(\tikzlastnode.south west)+(-0.015,-0.1)$) % to have some offset
rectangle ($(\tikzlastnode.north east)+(0.015,0.065)$);
}
}
}
}


gives:

Customizable offsets

With this improved version it is possible to customize the highlighted area (an idea borrowed from the hf-tikz package) via offsets. This offsets ultimately are pgfkeys whose values have to be declared within the optional argument of the \highlight command:

\highlight<overlay specification>[offsets]{text}


If no [offsets] are specified, the initial values are taken.

The code:

\documentclass{beamer}
\usepackage{lmodern}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{xparse}

\tikzset{
invisible/.style={opacity=0,text opacity=0},
visible on/.style={alt=#1{}{invisible}},
alt/.code args={<#1>#2#3}{%
\alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}}
},
}

\tikzset{
background fill/.style={fill=#1},
background fill/.default={white},
fill on/.style={alt=#1{}{background fill}},
}

\tikzset{
background draw/.style={draw=#1},
background draw/.default={white},
draw on/.style={alt=#1{}{background draw}},
}

\tikzset{
background filldraw/.style args={#1 filled by #2}{draw=#1, fill=#2},
background filldraw/.default=white filled by white,
filldraw on/.style={alt=#1{}{background filldraw}},
}

\pgfkeys{/highlight/.cd,
above right offset/.initial={0.015,0.065},
above right offset/.get=\aboverightoffset,
above right offset/.store in=\aboverightoffset,
below left offset/.initial={-0.015,-0.1},
below left offset/.get=\belowleftoffset,
below left offset/.store in=\belowleftoffset,
}

\tikzset{highlighting/.style={
append after command={
\pgfextra{
\path[rounded corners,
background filldraw=red filled by red!30,% border+filling
filldraw on=<#1>, % overlay specification
overlay] ($(\tikzlastnode.south west)+(\belowleftoffset)$) % to have some offset
rectangle ($(\tikzlastnode.north east)+(\aboverightoffset)$);
}
}
}
}

\NewDocumentCommand{\highlight}{r<> O{} m}{%
\pgfkeys{/highlight/.cd,#2}
\tikz[baseline=(A.base)]
\node[highlighting=#1,
inner sep=0pt] (A) {#3};%
}

\begin{document}

\begin{frame}{Itemize with styles}
\begin{itemize}[<+->]
\item Software-as-a-Service?
\item Platform-as-a-Service?
\item \highlight<5>{Infrastructure-as-a-Service}?
\item \highlight<6>[below left offset={-0.1,-0.2},above right offset={0.25,0.15}]{Other-stuff-as-a-Service}?
\end{itemize}
\end{frame}

\end{document}


The result:

-
Congratulations for having become a trusted user (rep > 20000)! –  egreg Apr 9 '13 at 16:53