42

Is there a simple way to have the body of a block environment in beamer to have a frame around it, rather than having a background colour? I tried putting a \fbox inside the block, but it just wrote off the side of the slide... I tried putting the fbox outside the block environment, but that looks mega ugly.

Ideally, I'd like to do this through defining a beamer template with \setbeamertemplate{blocks}{framed} or something like this. So that colour themes and blocks inside columns work nicely.

I looked up the definition of beamercolorbox and it's not pretty...

9
  • You can put a shadow around the bottom and right edge: \setbeamertemplate{blocks}[rounded][shadow=true]. (Not exactly what you want, but maybe it serves the same purpose.)
    – Alan Munn
    Feb 16, 2011 at 14:03
  • 2
    @Alan If it's possible to do that, it must be possible to have a simple frame around the block...
    – Seamus
    Feb 16, 2011 at 14:11
  • @Seamus: Well, there certainly does not seem to be an option for that, like there is one for shadow. I believe that beamer just creates a pgf node for the box, so it should be possible to "draw" the node, but I have no idea how. Feb 16, 2011 at 17:21
  • Hmm. Well, it might be a little ambitious to dig into the details for my presentation tomorrow, but I am exploring this at the weekend. (If someone doesn't beat me to it).
    – Seamus
    Feb 16, 2011 at 17:27
  • It's a bit of a dig to find where in the many subparts of beamer things are defined. So one has to really want to... :-)
    – Alan Munn
    Feb 16, 2011 at 23:28

5 Answers 5

38

With some serious butchering of beamerbaseboxes.aux I managed to get the following [framed] template for beamer boxes. For easier digestibility, I'll split the code into several chunks and add some comments inbetween. You'll probably want to move some parts to a .sty file.

It all starts, innocently, with

\documentclass{beamer}

Next, I took the code from \beamerboxesrounded, removed the shadow part, changed the drawinging commands a bit and changed some \vskips. First this sets up some colors. Then it sets the title in a minipage (that is saved to a box). Then it draws around the title. Finally it starts a minipage for the main content. The rest of the code glues things together.

\makeatletter
\newcommand\beamerboxesframed[2][]{%
  \global\let\beamer@firstlineitemizeunskip=\relax%
  \vbox\bgroup%
  \setkeys{beamerboxes}{upper=block title,lower=block body,width=\textwidth}%
  \setkeys{beamerboxes}{#1}%
  {%
    \usebeamercolor{\bmb@lower}%
    \globalcolorstrue%
    \colorlet{lower.bg}{bg}%
  }%
  {%
    \usebeamercolor{\bmb@upper}%
    \globalcolorstrue%
    \colorlet{upper.bg}{bg}%
  }%
  %
  % Typeset head
  %
  \vskip4bp
  \setbox\bmb@box=\hbox{%
    \begin{minipage}[b]{\bmb@width}%
      \usebeamercolor[fg]{\bmb@upper}%
      #2%
    \end{minipage}}%
  \ifdim\wd\bmb@box=0pt%
    \setbox\bmb@box=\hbox{}%
    \ht\bmb@box=0pt%
    \bmb@prevheight=-4.5pt%
  \else%
    \wd\bmb@box=\bmb@width%
    \bmb@temp=\dp\bmb@box%
    \ifdim\bmb@temp<1.5pt%
      \bmb@temp=1.5pt%
    \fi%
    \setbox\bmb@box=\hbox{\raise\bmb@temp\hbox{\box\bmb@box}}%
    \dp\bmb@box=0pt%
    \bmb@prevheight=\ht\bmb@box%
  \fi%
  \bmb@temp=\bmb@width%
  \bmb@dima=\bmb@temp\advance\bmb@dima by2.2bp%
  \bmb@dimb=\bmb@temp\advance\bmb@dimb by4bp%
  \hbox{%
    \begin{pgfpicture}{0bp}{+-\ht\bmb@box}{0bp}{+-\ht\bmb@box}
      \ifdim\wd\bmb@box=0pt%
        \color{lower.bg}%
      \else%
        \color{upper.bg}%
      \fi%
      \pgfpathqmoveto{-4bp}{-1bp}
      \pgfpathqcurveto{-4bp}{1.2bp}{-2.2bp}{3bp}{0bp}{3bp}
      \pgfpathlineto{\pgfpoint{\bmb@temp}{3bp}}
      \pgfpathcurveto%
      {\pgfpoint{\bmb@dima}{3bp}}%
      {\pgfpoint{\bmb@dimb}{1.2bp}}%
      {\pgfpoint{\bmb@dimb}{-1bp}}%
      \bmb@dima=-\ht\bmb@box%
      \advance\bmb@dima by-2pt%
      \pgfpathlineto{\pgfpoint{\bmb@dimb}{\bmb@dima}}
      \pgfpathlineto{\pgfpoint{-4bp}{\bmb@dima}}
      \pgfpathclose
      \pgfsetstrokecolor{black}\pgfusepath{stroke, fill}
    \end{pgfpicture}%
    \copy\bmb@box%
  }%
  \nointerlineskip%
  \ifdim\wd\bmb@box=0pt
  \else
    \vskip2.4pt%
  \fi%
  \nointerlineskip%
  \setbox\bmb@colorbox=\hbox{{\pgfpicturetrue\pgfsetcolor{lower.bg}}}%
  \setbox\bmb@box=\hbox\bgroup\begin{minipage}[b]{\bmb@width}%
    \vskip2pt%
    \usebeamercolor[fg]{\bmb@lower}%
    \colorlet{beamerstructure}{upper.bg}%
    \colorlet{structure}{upper.bg}%
    %\color{.}%
}

The end command ends the \minipage of the content and draws a line around it (not drawing on the top). Again I removed all the code for the shadow and changed the drawing code slightly.

\def\endbeamerboxesframed{%
  \end{minipage}\egroup%
  \wd\bmb@box=\bmb@width%
  \bmb@temp=\dp\bmb@box%
  \advance\bmb@temp by.5pt%
  \setbox\bmb@box=\hbox{\raise\bmb@temp\hbox{\box\bmb@box}}%
  \dp\bmb@box=0pt%
  \bmb@temp=\wd\bmb@box%
  \bmb@dima=\bmb@temp\advance\bmb@dima by2.2bp%
  \bmb@dimb=\bmb@temp\advance\bmb@dimb by4bp%
  \hbox{%
    \begin{pgfpicture}{0bp}{0bp}{0bp}{0bp}
      \unhbox\bmb@colorbox%
      \pgfpathmoveto{\pgfpoint{-4bp}{\ht\bmb@box}}
      \pgfpathlineto{\pgfpoint{-4bp}{1bp}}
      \pgfpathqcurveto{-4bp}{-1.2bp}{-2.2bp}{-3bp}{0bp}{-3bp}
      \pgfpathlineto{\pgfpoint{\the\bmb@temp}{-3bp}}
      \pgfpathcurveto%
      {\pgfpoint{\the\bmb@dima}{-3bp}}%
      {\pgfpoint{\the\bmb@dimb}{-1.2bp}}%
      {\pgfpoint{\the\bmb@dimb}{1bp}}%
      {
      \bmb@dima=\ht\bmb@box%
      \pgfpathlineto{\pgfpoint{\bmb@dimb}{\bmb@dima}}
      \pgfsetstrokecolor{black}\pgfusepath{stroke, fill}
      }
    \end{pgfpicture}%
    \box\bmb@box%
  }%
  \vskip2bp%
  \egroup% of \vbox\bgroup
}
\makeatother

Having defined the commands that do the actual drawing work, we need to set up the template. The following code is almost verbatim from beamerbaseauxtemplates.sty, only changing rounded to framed and removing shadow=false. If you want to, you can also remove the \vskip\smallskipamount (as the boxes are lighter, they can probably be placed closer together)

\defbeamertemplateparent{blocks}[framed]{block begin,block end,%
  block alerted begin,block alerted end,%
  block example begin,block example end}[1][]
{[#1]}

\defbeamertemplate{block begin}{framed}[1][]
{
  \par\vskip\medskipamount%
  \begin{beamerboxesframed}[upper=block title,lower=block body,#1]%
    {\raggedright\usebeamerfont*{block title}\insertblocktitle}%
    \raggedright%
    \usebeamerfont{block body}%
}
\defbeamertemplate{block end}{framed}[1][]
{\end{beamerboxesframed}\vskip\smallskipamount}

\defbeamertemplate{block alerted begin}{framed}[1][]
{
  \par\vskip\medskipamount%
  \begin{beamerboxesframed}[upper=block title alerted,lower=block body alerted,#1]%
    {\raggedright\usebeamerfont*{block title alerted}\insertblocktitle}%
    \raggedright%
    \usebeamerfont{block body alerted}%
}%
\defbeamertemplate{block alerted end}{framed}[1][]
{\end{beamerboxesframed}\vskip\smallskipamount}

\defbeamertemplate{block example begin}{framed}[1][]
{
  \par\vskip\medskipamount%
  \begin{beamerboxesframed}[upper=block title example,lower=block body example,#1]
    {\raggedright\usebeamerfont*{block title example}\insertblocktitle}%
    \raggedright%
    \usebeamerfont{block body alerted}%
}%
\defbeamertemplate{block example end}{framed}[1][]
{\end{beamerboxesframed}\vskip\smallskipamount}

Now we only have to select the template

\setbeamertemplate{blocks}[framed]

You might want to change some styling (depending on your theme, the defaults might look fine). Here is what I used for the example image.

\setbeamercolor{block title}{fg=black,bg=gray!40}
\setbeamercolor{block body}{fg=black,bg=gray!10}
\setbeamercolor{block title alerted}{fg=red,bg=gray!40}
\setbeamercolor{block title example}{fg=black,bg=green!20}
\setbeamercolor{block body example}{fg=black,bg=green!5}
\setbeamerfont{block title}{series=\bfseries}

An example:

\begin{document}
\begin{frame}
    \begin{block}{title}
        test

        a second line
    \end{block}

    \begin{block}{}
        test without title
    \end{block}

    \begin{alertblock}{title}
        test
    \end{alertblock}

    \begin{Example}
        test
    \end{Example}
\end{frame}
\end{document}

example

6
  • I will try out this answer this weekend and then accept! Would it be the same amount of hackery to get the square-edge boxes to have the same frame thing going on? Or is that easy now?
    – Seamus
    Mar 4, 2011 at 13:04
  • @Seamus: Which square-edge boxes. Do you mean to remove the rounded corners? That would mean to alter the \pgfpath... sections a bit (they will get simpler).
    – Caramdir
    Mar 4, 2011 at 16:45
  • I know it is an old answer. However would it be possible to make clear the settings for the radius and the line color?
    – Hotschke
    Sep 3, 2013 at 15:18
  • Or even better extend the answer to use \setbeamercolor and further options for the linecolor, linewidths and radius.
    – Hotschke
    Sep 3, 2013 at 15:27
  • 2
    This is excellent work, but it might be worth noting somewhere within the answer that there is now an official(?) package called tcolorbox that can do frames etc. with much less hackery. See @Ignasi's answer.
    – craq
    Aug 20, 2014 at 11:39
29

From its announcement in CTAN list (December, 2011)

tcolorbox provides an environment for colored and framed text boxes with a heading line. Optionally, such a box can be splitted in an upper and a lower part. The package tcolorbox can be used for the setting of LaTeX examples where one part of the box displays the source code and the other part shows the output. Another common use case is the setting of theorems. The package supports saving and reuse of source code and text parts.

Next there is an example using it inside beamer

\documentclass{beamer}
\usepackage[listings,theorems]{tcolorbox}
\begin{document}
\begin{frame}[fragile]
\begin{tcolorbox}[colback=blue!5,colframe=blue!75!black,title=My title]
  My box with my title.
\end{tcolorbox}

\begin{tcblisting}{colback=red!5,colframe=red!75!black}
\begin{tcolorbox}[colback=blue!5,colframe=blue!75!black,title=My title]
  My box with my title.
\end{tcolorbox}
\end{tcblisting}

\end{frame}
\end{document}

enter image description here

UPDATE:

I've played a little bit more with tcolorbox and also read the manual, so I discovered that it's possible to use TiKZ .styles. This way is easy to create groups of parameters (options) and reuse them. Next code tries to reproduce Caramdir's examples.

\documentclass{beamer}
\usepackage{tcolorbox}

% These options will be applied to all `tcolorboxes`
\tcbset{%
    noparskip,
    colback=gray!10, %background color of the box
    colframe=gray!40, %color of frame and title background
    coltext=black, %color of body text
    coltitle=black, %color of title text 
    fonttitle=\bfseries,
    alerted/.style={coltitle=red, 
                     colframe=gray!40},
    example/.style={coltitle=black, 
                     colframe=green!20,             
                     colback=green!5},
    }

\begin{document}

\begin{frame}
\begin{tcolorbox}[title=title]
  test

  a second line
\end{tcolorbox}

\begin{tcolorbox}
  test without title.
\end{tcolorbox}

\begin{tcolorbox}[alerted,title=title]
  test
\end{tcolorbox}

\begin{tcolorbox}[example,title=Example]
  test
\end{tcolorbox}
\end{frame}
\end{document}

The result is shown in next figure. With Caramdir's solution the frame border is always black and different from title background color. With tcolorbox frame border and title background use same color. I think skins library (see manual) could solve this problem(?).

enter image description here

7

I seized the ideas and answers of @Caramdir and @Ignasi to create a block template with tcolorbox. Add the following code to your beamer theme file (e.g., beamerthemeFramedBoxes.sty):

\usepackage{tcolorbox}

\defbeamertemplateparent{blocks}[framed]{block begin,block end}[1][]
{[#1]}

\defbeamertemplate{block begin}{framed}[1][]
{
  \begin{tcolorbox}[%
    colback=white,%
    colframe=gray, arc=0mm]%
    {\vskip\smallskipamount%
      \raggedright\usebeamerfont*{block title}%
      \usebeamercolor[fg]{title}\insertblocktitle}%
    \vskip\smallskipamount%
    \raggedright%
    \usebeamerfont{block body}%
  }

\defbeamertemplate{block end}{framed}[1][] {\end{tcolorbox}}

\setbeamertemplate{blocks}[framed]

This creates a block template called framed that has framed borders. It does not create alert and example block templates and it does not use the background colors of beamer yet and it does not correctly set the title. All of this could be implemented easily though, if really needed.

2
  • I have tried to use your code, and although it compiles there are no frames around the blocks. Could you tell me if I need to label the blocks as 'framed blocks' after using your code?
    – Vass
    Sep 13, 2017 at 18:30
  • Hm, no, if you set the default beamer template of blocks to framed (second and last line in the script), you should not need any additional configuration. Maybe your border colors are white, if you have a white background? Sep 15, 2017 at 8:24
3

Here's a proof of concept for an alternative solution that doesn't involve quite as much hackery as Caramdir's solution did.

\documentclass{beamer}
\usepackage{mdframed}
\newenvironment{framedblock}[1]{%
  \begin{mdframed}[skipbelow=-1pt]
    #1
  \end{mdframed}
  \begin{mdframed}[skipabove=0pt]
}{
\end{mdframed}
}
\begin{document}
\begin{frame}
\begin{framedblock}{Title}
 This block is framed
\end{framedblock}
\end{frame}
\end{document}

It doesn't use beamer's block interface, but it should be possible to make it use beamer colours, with a little fiddling...

The spacing is currently suboptimal. I shall play with that later. Also, mdframed can do rounded corners, so I'll play with that too...

2

You could use the new tcolorbox inner theme (https://www.ctan.org/pkg/beamertheme-tcolorbox ) as starting point and add a borderline to it:

\documentclass{beamer}
\usetheme{Warsaw}

\useinnertheme{tcolorbox}

\makeatletter
\tcbset{
  boxrule=1pt,
  borderline={1.5pt}{0pt}{beamer@tcb@titlebg},
}
\makeatother

\begin{document}

\begin{frame}

\begin{block}{title}
content...
\end{block}

\end{frame}
\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 .