[Tex/LaTex] How to adjust the beamer block width to the size of its content

beamerhighlighting

I would like to define a nice beamer block environment with the following properties

a) it is always centered on the slide (horizontally)
b) it is only slightly longer than its content

The aim is to put an equation inside the block and use the block as a highlighter for this equation. So in short, I want a block environment that adjusts its width to the content it contains. Does anybody know a solution?

This would be an example of what I want to achieve automatically:

\documentclass[slidestop]{beamer}
\usetheme{Madrid}
\begin{document}

\begin{frame}{Test}
\abovedisplayskip=0pt 

\begin{center}
\begin{minipage}{0.2\textwidth}
\begin{block}{}
\begin{gather*}
c^2=a^2+b^2
\end{gather*}
\end{block}
\end{minipage}
\end{center}

\end{frame}
\end{document}

The environment should work similar like this manual hack with the improvement that the 0.2\textwidth is adjusted nicely according to the actual width of the formula.

Edit:

I am searching for a nice realization of the following workaround:

\documentclass[slidestop]{beamer}
\usetheme{Madrid}
\usepackage{calc}


\newcommand{\gatherblock}[1]{%
\vspace*{-5pt}
\begin{center}
\begin{minipage}{\widthof{$#1$}}
\begin{block}{}
\abovedisplayskip=0pt 
\vspace*{-1pt}
\begin{gather*}
#1
\end{gather*}
\end{block}
\end{minipage}
\end{center}}


\begin{document}
\begin{frame}{Test}

\gatherblock{c^2=a^2+b^2}

\end{frame}

Best Answer

If your aim is to highlight equations without having to care about its width you could use other approaches rather than blocks.

I propose here two methods:

Solution with minimal spacing

This method needs the tikzmark library: it could be find at http://bazaar.launchpad.net/~tex-sx/tex-sx/development/files, then download the files tikzmark.dtx and tikzmark_example.pdf. Once put in a temporary directory compile with pdflatex, then install is as a package.

The code:

\documentclass[t]{beamer}
\usepackage{lmodern}
\usetheme{Madrid}

\usepackage{tikz}
\usetikzlibrary{calc,shapes,shadows,tikzmark}

% setting the block body color
\usebeamercolor{block body}
\definecolor{my block body}{named}{bg}

% Original by Peter Grill:
% https://tex.stackexchange.com/questions/35319/a-boxed-alternative-with-minimal-spacing/#35357

\makeatletter
\newcommand*{\@DrawBoxHeightSep}{0.3ex}%
\newcommand*{\@DrawBoxDepthSep}{0.1em}%
\newcommand{\@DrawBox}[6][fill=my block body,draw=my block body!50!black]{
%#1= style,#2=height, #3=depth, #4 left marker,
%#5= right marker, #6= content
\tikz[overlay,remember picture,baseline]
 \draw[#1,drop shadow,rounded corners]
  ($(pic cs:#4)+(-0.2em,#2+\@DrawBoxHeightSep)$) rectangle
  ($(pic cs:#5)+(0.2em,-#3-+\@DrawBoxDepthSep)$);
\tikz[overlay,remember picture,baseline]
 \node[anchor=base] at ($(pic cs:#4)!0.5!(pic cs:#5)$) {#6};
}

\newcounter{image}
\setcounter{image}{1}
\newdimen\@myBoxHeight%
\newdimen\@myBoxDepth%
\newcommand{\NiceBlock}[2][fill=my block body,draw=my block body!50!black]{%
 \settoheight{\@myBoxHeight}{#2}% Height
 \settodepth{\@myBoxDepth}{#2}% Depth
 \tikzmark{l\theimage}#2\tikzmark{r\theimage}
\@DrawBox[#1]{\@myBoxHeight}{\@myBoxDepth}
  {l\theimage}{r\theimage}{#2}
 \stepcounter{image}
}
\makeatother

\begin{document}

\begin{frame}{Test}
\begin{gather*}
\NiceBlock{\ensuremath{c^2=a^2+b^2}}
\end{gather*}


\begin{gather*}
\NiceBlock{\ensuremath{x+z=100}}
\end{gather*}

\end{frame}
\end{document}

After two compilation runs, the result is:

enter image description here

Solution with hf-tikz

The previous solution is completely automatic, but could have some problems. Suppose to box:

\begin{gather*}
\NiceBlock{\ensuremath{
\sum_{l _1+\dots+ l _p=l}\prod^p_{i=1} \binom{n_i}{l _i}
}
}
\end{gather*}

You will end up with:

enter image description here

This because of one cannot say:

\NiceBlock{
\begin{gather*}
\sum_{l _1+\dots+ l _p=l}\prod^p_{i=1} \binom{n_i}{l _i}
\end{gather*}
}

That's the reason why a semi-automatic package like hf-tikz IMHO provides a good alternative: markers fit pretty well the dimensions automatically, but when needed the user could shift and extend as he needs the highlighted area.

An example that shows how to highlight some equations with overlay specifications:

\documentclass[t]{beamer}
\usepackage{lmodern}
\usetheme{Madrid}
\usepackage[beamer,customcolors]{hf-tikz}

% setting the block body color
\usebeamercolor{block body}
\definecolor{my block body}{named}{bg}
\hfsetbordercolor{my block body!50!black}
\hfsetfillcolor{my block body}

\begin{document}

\begin{frame}{Test}
\begin{gather*}
\tikzmarkin<1->{a}(0.15,-0.1)(-0.15,0.4)c^2=a^2+b^2\tikzmarkend{a}
\end{gather*}

\begin{gather*}
\tikzmarkin<2->{x}x+z=100\tikzmarkend{x}
\end{gather*}

\begin{gather*}
\tikzmarkin<{1,3}>{c}(0.15,-0.6)(-0.15,0.7)
\sum_{l _1+\dots+ l _p=l}\prod^p_{i=1} \binom{n_i}{l _i}
\tikzmarkend{c}
\end{gather*}

\end{frame}
\end{document}

Also in this case two compilation runs are necessary; then the result is:

enter image description here


If instead you want to use blocks, there could be another solution, but is not automatic. Moreover, in contrast with hf-tikz where the overlay specification is just used to show or not the highlighting, here the equation is inside a block, so the overlay specifications show or not the equation with the block together.

Code:

\documentclass[t]{beamer}
\usepackage{lmodern}
\usetheme{Madrid}
\usepackage[customcolors,shadow,roundedcorners]{dynblocks}
% setting the block body color
\usebeamercolor{block body}
\definecolor{my block body}{named}{bg}
\setbordercolor{my block body}
\setblockcolor{my block body}

% new enviroment always centered
\newenvironment{cdynblock}{\begin{center}\begin{dynblock}}{\end{dynblock}\end{center}}

\begin{document}

\begin{frame}{Test}
\abovedisplayskip=0pt
\begin{cdynblock}
\opaqueblock<1->[0.2\textwidth]{
\begin{gather*}
c^2=a^2+b^2
\end{gather*}
}
\end{cdynblock}

\begin{cdynblock}
\opaqueblock<2->[0.2\textwidth]{
\begin{gather*}
x+y=400
\end{gather*}
}
\end{cdynblock}

\begin{cdynblock}
\opaqueblock<3->[0.3\textwidth]{
\begin{gather*}
\sum_{l _1+\dots+ l _p=l}\prod^p_{i=1} \binom{n_i}{l _i}
\end{gather*}
}
\end{cdynblock}
\end{frame}

\end{document}

The result:

enter image description here

Using the dynblocks and environ packages, allows to compute automatically the width of the formula.

Here is the key point:

% new enviroment always centered

\usepackage{environ}
\newsavebox\mybox
% new environment cdyn: #1 => overlay specification
\NewEnviron{cdyn}[1]{%
    \sbox{\mybox}{$\BODY$}%
    \begin{center}
    \begin{dynblock}
    \opaqueblock<#1>[\wd\mybox]{\[\BODY\]}
    \end{dynblock}
    \end{center}
}{}%

in which first I compute the width of the formula and then this width is passed to the \opaqueblock command.

The complete code:

\documentclass[t]{beamer}
\usepackage{lmodern}
\usetheme{Madrid}
\usepackage[customcolors,shadow,roundedcorners]{dynblocks}
% setting the block body color
\usebeamercolor{block body}
\definecolor{my block body}{named}{bg}
\setbordercolor{my block body}
\setblockcolor{my block body}

% new enviroment always centered

\usepackage{environ}
\newsavebox\mybox
% new environment cdyn: #1 => overlay specification
\NewEnviron{cdyn}[1]{%
    \sbox{\mybox}{$\BODY$}%
    \begin{center}
    \begin{dynblock}
    \opaqueblock<#1>[\wd\mybox]{\[\BODY\]}
    \end{dynblock}
    \end{center}
}{}%

\begin{document}

\begin{frame}{Test}
\abovedisplayskip=0pt

\begin{cdyn}{1-}
c^2=a^2+b^2
\end{cdyn}

\begin{cdyn}{2-}
x+y=400
\end{cdyn}

\begin{cdyn}{3-}
\sum_{l _1+\dots+ l _p=l}\prod^p_{i=1} \binom{n_i}{l _i} + 
\sum_{l _1+\dots+ l _p=l}\prod^p_{i=1} \binom{n_i}{l _i}
\end{cdyn}

\begin{cdyn}{4-}
q_{n+1}=q_n-\Delta_n+\theta_n \qquad \Delta_n=
\begin{cases}
1 \quad q_n>0\\
0 \quad q_n=0
\end{cases}
\end{cdyn}

\end{frame}

\end{document}

The result:

enter image description here

Related Question