निरंजन
I want a border in `standalone` document class. This is a code that I found on TeX.SE in [this](https://tex.stackexchange.com/a/808/174620) answer, but apparently it doesn't work for `\documentclass{standalone}`.
```
\documentclass[border=6cm]{standalone}
\usepackage{pgf}
\usepackage{pgfpages}
\pgfpagesdeclarelayout{boxed}
{
\edef\pgfpageoptionborder{0pt}
}
{
\pgfpagesphysicalpageoptions
{%
logical pages=1,%
}
\pgfpageslogicalpageoptions{1}
{
border code=\pgfsetlinewidth{2pt}\pgfstroke,%
border shrink=\pgfpageoptionborder,%
resized width=.95\pgfphysicalwidth,%
resized height=.95\pgfphysicalheight,%
center=\pgfpoint{.5\pgfphysicalwidth}{.5\pgfphysicalheight}%
}%
}
\pgfpagesuselayout{boxed}
\begin{document}
Hello world
\end{document}
```
I have these requirements.
* Borders that can be added **after** the blank space provided by the optional argument `border=xx` to the `documentclass`.
* Multiple borders i.e. I shall be able to nest the borders by adding more on top of them.
* User defined widths.
Is there any package already available to achieve this?
Top Answer
Skillmon
You could get what you want (if I understood correctly) using `\fbox` and no additional packages:
```
\documentclass[border=3mm]{standalone}
\setlength\fboxsep{6cm}
\setlength\fboxrule{2pt}
\begin{document}
\fbox{Hello world}
\end{document}
```
![boxy_stuff-1.png](/image?hash=fa8a6a728503d493742cf65168b65fcc34935bdc3fb023393fd5fffff3e7801d)
Answer #2
user 3.14159
Here is a `tcolorbox` solution.
```
\documentclass[border=3mm]{standalone}
\usepackage{tcolorbox}
\begin{document}
\tcbox[colback=white,boxsep=6cm]{Hello world}
\end{document}
```
![Screen Shot 2020-08-10 at 11.21.24 AM.png](/image?hash=f648fb5bf2a5501b4b2c2a70b8d831ab5dcf1c8e1b798e37e42894d7c3c1f43b)
In its basic usage it is not too different from the [`\fbox` solution provided by Skillmon](https://topanswers.xyz/tex?q=1228#a1460), yet it is arguably much easier to customize. Apart from the rounded corners (which you can control with the `arc` key) you have a whole abundance of other ways to customize the output. For instance, you can change the distances arbitrarily with the `top` and so on keys (see p. 42 of the tcolorbox 4.30 manual), add shadows etc. The list of options is quite large, the `tcolorbox` manual has over 500 pages.
If you want to add several boxes in a document, each of which getting cropped and framed, you may want to use the `\standaloneenv` command and the `hbox` key.
```
\documentclass[border=3mm]{standalone}
\usepackage{tcolorbox}
\newtcolorbox{mybox}[1][]{hbox,colback=white,boxsep=6cm,#1}
\standaloneenv{mybox}
\begin{document}
\begin{mybox}
Hello world!
\end{mybox}
\begin{mybox}[toprule=2mm]
Hello ducks!
\end{mybox}
\end{document}
```
![ani.gif](/image?hash=1fa033f793f38395831388a97e66242a4a0a9885ea33aa38c1e6acfc76e32cd2)
Answer #3
Skillmon
# `\multibox`
The following provides code with which nested `\fbox` usages are generated. I use `expkv-def` and `expkv-cs` for this, but the basic approach doesn't depend on those two and could be created with most (if not all) key=val packages.
## Explanation
So what is the basic idea? We provide two sets of keys, the first is those defined with `\ekvdefinekeys`. They set the defaults and allow to change them (`sep`, `rule`, `reset sep`, `reset rule`) and call the next set of keys when you add a frame (`add frame`, `set frame`). The key `add frames` is only using the defaults and doesn't call the second key-set.
The next set of keys only contains the two keys `sep` and `rule`, it is defined with `\ekvcSplitAndForward`. These produce either the current defaults as defined in the first set of keys (stored in two `dimen` registers) or the arguments given by the user. They don't need to make assignments, which eases their usage. If we didn't use `expkv-cs` for those, we could use another set of `dimen` registers instead to temporarily store the user input.
All these keys from both sets are just to call `\multibox@set` with the correct arguments, and that one creates the nested `\fbox` structure stored in the macro `\multibox@do`. The third argument of `\multibox@set` is either `\unexpanded{\usebox\multibox@box}` (which means to drop the current box structure) or `\unexpanded\expandafter{\multibox@do}` (which means to add another box around the current box structure).
After one call to `\multibox@set` without resetting the box structure the macro `\multibox@do` will contain
```
\setlength\fboxsep{<sep1>}%
\setlength\fboxrule{<rule1>}%
\fbox{\usebox\multibox@box}%
```
a second call will result in
```
\setlength\fboxsep{<sep2>}%
\setlength\fboxrule{<rule2>}%
\fbox
{%
\setlength\fboxsep{<sep1>}%
\setlength\fboxrule{<sep2>}%
\fbox{\usebox\multibox@box}%
}%
```
and so on. Each `\fbox` creates a scope, so the changes to `\fboxsep` and `\fboxrule` of the inner `\fbox`es don't affect the outer ones.
Finally the output is aided by the `grabbox` package. All the macro call `\@grabbox{}\multibox@box{}\hbox{}{\multibox@do\endgroup}` does is to call something like
```
\newcommand\foo[1]
{%
\setbox\multibox@box\hbox{{#1}}%
\multibox@do
\endgroup
}
```
but all that without having to actually grab the box content as an argument. Instead it will be directly typeset into the box, so that `\multibox@do` can use the box contents by accessing the box register `\multibox@box`. For this last step there would also be alternatives. The easiest one would be to just grab the argument, another alternative would be the `collectbox` package, which does roughly the same as `grabbox` (a slightly different approach, iirc, and I wouldn't have written `grabbox` if I had known `collectbox` before).
As a result, the mandatory argument to `\multibox` *must* be enclosed by braces, else you'd get a `missing { inserted` error.
----
## Code
So with that lengthy explanation of the concept out of the way, here is the complete code:
```
\documentclass[border=3mm]{standalone}
\usepackage{expkv-def,expkv-cs}
\usepackage{grabbox}
\makeatletter
\newsavebox\multibox@box
\ekvdefinekeys{multibox}
{
protect code add frame =
\multibox@split{#1}{\unexpanded\expandafter{\multibox@do}}
,default add frame = {}
,protect code set frame =
\multibox@split{#1}{\unexpanded{\usebox\multibox@box}}
,default set frame = {}
,protect code add frames = \multibox@multadd{#1}
,dimen sep = \multibox@sep
,initial sep = \fboxsep
,dimen rule = \multibox@rule
,initial rule = \fboxrule
,nmeta reset = { reset sep , reset rule , reset box }
,nmeta reset sep = sep = \fboxsep
,nmeta reset rule = rule = \fboxrule
,noval reset frame = \def\multibox@do{\usebox\multibox@box}
}
\ekvsetdef\multiboxSet{multibox}
\newcommand*\multibox@do{\usebox\multibox@box}
\ekvcSplitAndForward\multibox@split\multibox@set
{
long sep = \multibox@sep
,long rule = \multibox@rule
}
\newcommand*\multibox@set[3]
{%
\edef\multibox@do
{%
\unexpanded{\setlength\fboxsep}{\the\dimexpr#1}%
\unexpanded{\setlength\fboxrule}{\the\dimexpr#2}%
\noexpand\fbox{#3}%
}%
}
\newcommand*\multibox@multadd[1]
{%
\expanded
{%
\unexpanded
{%
\count\z@=\z@
\loop\ifnum#1>\count\z@
\advance\count\z@\@ne
\multibox@set
{\multibox@sep}%
{\multibox@rule}%
{\unexpanded\expandafter{\multibox@do}}%
\repeat
}%
\count\z@=\the\count\z@\relax
}%
}
\newcommand*\multibox[1][]
{%
\begingroup
\multiboxSet{#1}%
\@grabbox{}\multibox@box{}\hbox{}{\multibox@do\endgroup}%
}
\makeatother
\multiboxSet
{
add frames = 2 % add two boxes using the defaults
,add frame = {sep=5mm} % add a custom box with default thickness
,add frame = {rule=1cm} % add a custom box with default sep
,add frame = {sep=5mm, rule=1cm} % add a custom box
,add frame % add a box using the defaults
}
\begin{document}
\multibox
[
sep = 2pt % change the default sep
,rule = 3pt % change the default thickness
,add frames = 2 % add two boxes using the defaults
]
{Hello \verb|world|}
\end{document}
```
----
## Showcase
Since the above uses only `\fbox`, it can only produce boring boxes, but many of them at once.
![boxy_stuff-1.png](/image?hash=b30ae12dbe31bf62093b280dcfd916cbe0338064b23233e51ab699a1feb74522)
![boxy_stuff-2.png](/image?hash=77f21c6a90a0d23cfb4fa40c5a410eecd92cd506407db77acae830473f590c07)
![boxy_stuff-3.png](/image?hash=c81fe912b501bf5bd4545612c4ed151a1d0fb41116a5ea3c077d461c2f35ffbc)
![boxy_stuff-4.png](/image?hash=d213491ca9276d4a5beacf470414b42a2697eb23ae2bb4cd7d676771874143dd)