# Draw an automatic “bounding box”?

I have some Tikz figures in my document and want to draw a frame around it. The width of this frame should be always \textwidth. The height should be automatically adjusted to the height of the actual Tikz object. Is there a general solution which is independent of the Tikz object size?

Here my first try, which doesn't work. How can I overlap the red and black frame? (This is just an example to illustrate the problem. Usually the black rectangle is an arbitrary Tikz object.)

\documentclass{scrbook}
\usepackage{tikz}
\usepackage{blindtext}

\begin{document}
\blindtext
\begin{figure}[h]
\begin{tikzpicture}
\node(boundbox) [draw=red] {
\begin{tikzpicture} % could be an arbitrary complex Tikz object
\draw (0,0) rectangle (\textwidth,0.5);
\end{tikzpicture}
};
\end{tikzpicture}
\end{figure}
\blindtext
\end{document}

-
\framebox[\textwidth]{<your TikZ picture>}? Why are you nesting TikZ picture? What do the red and black frames represent? The outer node will have inner xseps and such active. I wouldn’t use an extra TikZ picture to draw a box around it. –  Qrrbrbirlbel Nov 21 '13 at 18:59
@Qrrbrbirlbel, \noindent is necessary in this case together your solution. –  Sigur Nov 21 '13 at 19:01
@Sigur Not inside figure (or any other float environment, I guess). But outside, you better use \par\noindent before it, yes. –  Qrrbrbirlbel Nov 21 '13 at 19:03
@Sigur Or \centering in the figure environment. –  egreg Nov 21 '13 at 19:03
@qrrbrbirlbel: Thanks, this is exactly what I want. Sometimes it is so easy... ;) The red box is the "bounding box", the black box represents the Tikz object. –  user4811 Nov 21 '13 at 19:04

For a basic solution, you can use (which would disallow verbatim content in nodes):

\framebox[\textwidth]{<TikZ picture>}


For a TikZ solution the backgrounds library already offers a show background rectangle key (alias: framed). With a proper inner frame xsep setting we can accomplish a “framebox” very easily. As the frame actually adds more width (half the linewidth on both sides), we need to slightly change the definition of the background path.

Obviously, we would want to add this correction directly to the calculation of the inner frame xsep value but we couldn’t guarantee that it picks up the correct \pgflinewidth (as the calculation is done outside of the path). We could obviously hard-code it (related reference: [1]) but then we couldn’t use different line-width for different frames (which we probably won’t (and shouldn’t), though).

Alternatively, protruding half the linewidth into the margins with

background rectangle/.append code={\tikz@addmode{\pgf@relevantforpicturesizefalse}}


## Code

\documentclass{scrartcl}
\usepackage{tikz}
\usepackage[showframe,pass]{geometry}
\usetikzlibrary{backgrounds}
\makeatletter
\tikzset{inner frame xsep=.5\textwidth-.5\pgf@picmaxx+.5\pgf@picminx}
\def\tikz@background@framed{% just overwriting the original definition
\tikz@background@save%
\pgfonlayer{background}
\path[style=background rectangle] (\tikz@bg@minx+.5\pgflinewidth,\tikz@bg@miny) rectangle (\tikz@bg@maxx-.5\pgflinewidth,\tikz@bg@maxy);
\endpgfonlayer}
\makeatother
\newcommand*\arbitrarycomplexTikZobject[1][]{
\begin{tikzpicture}[#1] % could be an arbitrary complex Tikz object
\filldraw[opacity=.4] (0,0) rectangle node[text=white,scale=5,opacity=1] {Ti\emph{k}Z} (.5\textwidth,2cm);
\end{tikzpicture}}
\begin{document}
Space.
\begin{figure}[ht]
\framebox[\textwidth]{\arbitrarycomplexTikZobject}
\caption{Frame with \texttt{\string\framebox}.}
\end{figure}
\tikzset{every picture/.append style={framed}}
\begin{figure}[ht]
\arbitrarycomplexTikZobject
\caption{Frame with the \texttt{framed} option and a nice \texttt{inner frame xsep} setting.}
\end{figure}
\begin{figure}[ht]
\arbitrarycomplexTikZobject[background rectangle/.append style={ultra thick,draw=red,top color=blue,rounded corners}]
\caption{Frame with the \texttt{framed} option, a nice \texttt{inner frame xsep} setting and a badass frame which is taken from the Ti\emph{k}Z manual but without the \texttt{double} option.}
\end{figure}
\end{document}


## Output

-
very nice, thanks! –  user4811 Nov 21 '13 at 19:50

Another option to frame your figures is tcolorbox. By default it adjusts box with to line width.

\documentclass[a4paper]{article}
\usepackage{tikz}
\usepackage{blindtext}
\usepackage{tcolorbox}
\tcbuselibrary{skins}

\begin{document}
\blindtext
\begin{figure}[h]
\begin{tcolorbox}\centering
\begin{tikzpicture}
\filldraw[opacity=.4] (0,0) rectangle node[text=white,scale=5,opacity=1] {Ti\emph{k}Z} (.5\textwidth,2cm);
\end{tikzpicture}
\end{tcolorbox}
\caption{\texttt{tcolorbox} example}
\end{figure}
\begin{figure}[h]
\begin{tcolorbox}[beamer,colback=red!5!white,colframe=red!75!black,]\centering
\begin{tikzpicture}
\filldraw[opacity=.4] (0,0) rectangle node[text=white,scale=5,opacity=1] {Ti\emph{k}Z} (.5\textwidth,2cm);
\end{tikzpicture}
\end{tcolorbox}
\caption{\texttt{tcolorbox} example}
\end{figure}
\end{document}


-

Another solution, assuming your figures are centered.

The idea is to draw an empty node of \textwidth and determine the height using the fit library and the bounding box created by the TikZ drawing.

## Code

\documentclass{scrbook}
\usepackage{tikz}
\usetikzlibrary{fit}
\usepackage{lipsum}

\begin{document}
\lipsum[1]

\begin{figure}[h]
\begin{tikzpicture}
% arbitrary TikZ picture begins ---------------
\filldraw[opacity=.4] (0,0) rectangle node[text=white,scale=5,opacity=1] {Ti\emph{k}Z} (.5\textwidth,2cm);
% arbitrary TikZ picture ends -----------------
\node[
draw=red,
minimum width=\textwidth,
fit=(current bounding box.north west) (current bounding box.south east),
]at (current bounding box.center){};
\end{tikzpicture}
\caption{Figure Title}
\end{figure}

\lipsum[2]
\end{document}


## Alternative horizontal alignment

If instead of aligning the TikZ drawing at center, one wants to left-align （or right-align) it, then simply change the node position from at (current bounding box.center) to at (current bounding box.east) (or at (current bounding box.west) for right-alignment).

\begin{figure}[h]
\begin{tikzpicture}
% arbitrary TikZ picture begins ---------------
\filldraw[opacity=.4] (0,0) rectangle node[text=white,scale=5,opacity=1] {Ti\emph{k}Z} (.5\textwidth,2cm);
% arbitrary TikZ picture ends -----------------
\node[
draw=red,
minimum width=\textwidth,
fit=(current bounding box.north west) (current bounding box.south east),
]at (current bounding box.east){};
\end{tikzpicture}
\caption{Figure Title}
\end{figure}


-