Longfbox
Longfbox
Longfbox
Daan Leijen
2015-12-05
Contents
1. Introduction 1
2. Overview 2
3. Styling with CSS 4
3.1. Borders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.1.1. Border style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.1.2. Border width . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.1.3. Border color . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.1.4. Border corner radius . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2. Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3. Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.4. Padding and margins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.5. Breaking content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.6. Height and width . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.7. Predefined styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4. Advanced topics 18
4.1. Hooks and rendering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.2. Internal attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.3. Customizing border dashes and dots . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1. Introduction
The longfbox package provides framed boxes that can be customized using
standard CSS attributes. It was written to support precise rendering of Madoko
documents in LATEX. Notable features are:
• Specify the boxes using standard CSS attributes like border-style=dashed
or border-top-left-radius=10pt. Almost all of the CSS 2.0 attributes
with regard to borders, background, padding, and margins are supported.
• Fast and portable: only uses the standard LATEX picture environment
for drawing and does not depend on loading big packages like tikz or
1
pstricks, which makes running LATEX much faster.
• Supports breakable boxes that span multiple columns or pages. This pack-
age builds on the longbox package to break boxes over multiple pages.
• Much care has been put in precise rendering with proper baseline align-
ment and no spurious extra whitespace.
• In contrast to larger packages like mdframed or tcolorbox, the longfbox
package does not have more extensive features like frame titles, middle
lines, skins, etc. The focus of this package is on rendering boxes well with
full CSS support where every corner and side can be styled separately with
good looking transitions, where we only depend on the standard picture
environment.
2. Overview
There are two ways to create a framed box, the environment longfbox and the
command \lfbox.
\lfbox[⟨options⟩]{⟨content⟩}
The ⟨options⟩ are optional and specify CSS attributes. Just like the regular
\fbox command, the \lfbox command sets the content in a horizontal box and
cannot break the content over multiple lines (but it can contain other boxes like
a \parbox or minipage environment.). The default width of an \lfbox is the
natural width of its content. This corresponds to a CSS inline element.
\begin{longfbox}[⟨options⟩]⟨content⟩\end{longfbox}
The longfbox environment sets the content in a long vertical box and can
break content over multiple columns or pages. The default width is the current
\linewidth. This corresponds to a CSS block element.
2
\begin{longfbox}
The \textsf{longfbox} can contain much
longer content and will by default be
as wide as the current line width.
\end{longfbox}
The longfbox can contain much longer content and will by default be as
wide as the current line width.
\newfboxstyle{⟨name⟩}{⟨options⟩}
Defines a new style that can be used to specify commonly used options. For
example, the package defines:
\newfboxstyle{tight}{padding=0pt,margin=0pt,baseline-skip=false}
The new style tight can now be used to render a tight box:
The \lfbox and longfbox environment can replace many commands in LATEX
through the rich CSS interface. In particular:
• framed, \framebox, \fbox: through the text-align and width attributes.
• minipage, \parbox: through the width, text-align, vertical-align and
baseline attributes.
• \makebox: through border-style=none and the text-align and width at-
tributes.
• \raisebox: through the raise attribute.
• \colorbox, \fcolorbox: through the background-color attribute.
• \doublebox, \ovalbox: through the double border style, and the border-radius
attribute.
• \shadowbox: soon :-)
\fboxset{⟨options⟩}
Options can be set for the current scope through this declaration. For example,
to make all borders rounded and red by default, use:
3
margin-top border-top-width
top-left-radius padding-top
content-box
height
margin-left padding-left padding-right margin-right
width
border-left-color margin-bottom
Figure 1. Attributes of the longfbox are modeled after the corresponding CSS
attributes. Borders are drawn using the standard picture environment.
\fboxset{rounded,border-color=red}%
Here is a \lfbox{rounded} box.
Here is a
\lfbox[
border-width=0.8pt,
border-left-color=red,
border-style=dotted,
padding={0.2ex,0.4ex}, %top&bottom, right&left
]{fancy} box.
4
Here is another example using the longfbox environment:
\begin{longfbox}[
margin-right=6em,
padding=1.5em,
background-color=floralwhite,
background-clip=padding-box,
border-width=2pt,
border-radius=15pt,
border-top-left-radius=30pt,
border-left-width=8pt,
border-left-color=teal,
border-right-style=double,
]
A \textsf{longfbox} example. A longfbox can contain much
longer content and will by default be as
wide as the current line width.
\end{longfbox}
3.1. Borders
The border options determine how the frame of the box is rendered.
border-style=⟨style sides⟩
border-top-style=⟨style⟩ (=solid)
border-right-style=⟨style⟩ (=solid)
border-bottom-style=⟨style⟩ (=solid)
border-left-style=⟨style⟩ (=solid)
5
| inset | outset | groove | ridge
The ⟨style sides⟩ value can take 1 to 4 style arguments just like in CSS:
\lfbox[border-style=solid]{solid},
\lfbox[border-style=dashed]{dashed},
\lfbox[border-style=dotted]{dotted},
\lfbox[border-style=double,border-width=2pt]{double},
\lfbox[border-style={solid,none,dashed,none}]{various}.
Note, for a dotted border, it is often nicer to use the dotted style (Section 3.7)
since it makes the dots a bit larger, e.g.
The final CSS styles darken sides of the border to give a 3D effect:
\lfbox[border-style=inset,border-color=red,border-width=3pt]{inset},
\lfbox[border-style=outset,border-color=red,border-width=3pt]{outset},
\lfbox[border-style=groove,border-color=teal,border-width=4pt]{\strut groove},
\lfbox[border-style=ridge,border-color=teal,border-width=4pt]{\strut ridge}.
The darkness can be controlled using the border-dark-mix attribute (Section 3.1.3).
Beyond CSS, there are also styles for the border top and bottom when a box
is broken over multiple pages (see Section 3.5):
border-break-style=⟨style break-sides⟩
border-break-top-style=⟨style⟩ (=none)
6
border-break-bottom-style=⟨style⟩ (=none)
⟨attr break-sides⟩=⟨attr⟩
| {⟨break-top-attr⟩, ⟨break-bottom-attr⟩}
border-width=⟨width sides⟩
border-top-width=⟨dimen⟩ (=\fboxrule)
border-right-width=⟨dimen⟩ (=\fboxrule)
border-bottom-width=⟨dimen⟩ (=\fboxrule)
border-left-width=⟨dimen⟩ (=\fboxrule)
This sets the width of each border. By default the \fboxrule width is used
which is normally 0.4pt.
A \lfbox[border-width=3pt,border-left-color=red]{thick} border,
and
\lfbox[border-top-width=0pt,border-bottom-width=1pt]{varied}.
border-break-width=⟨width break-sides⟩
border-break-top-width=⟨dimen⟩ (=0pt)
border-break-bottom-width=⟨dimen⟩ (=0pt)
These specify border width around page breaks. See Figure 2 in Section 3.5 for
more information.
border-color=⟨color sides⟩
border-top-color=⟨color⟩ (=black)
7
border-right-color=⟨color⟩ (=black)
border-bottom-color=⟨color⟩ (=black)
border-left-color=⟨color⟩ (=black)
Colors can be specified by a name (e.g. red), and xcolor package color specifi-
cation (e.g. red!60), a direct HTML color (e.g. \#800080) or as an empty value.
The empty value is used for transparency on backgrounds.
Strange
\lfbox[border-width=3pt,
border-top-color=red!50,
border-bottom-color=\#800080,
]{colors}.
\noindent\begin{longfbox}[border-style=none,
border-left-style=solid,
border-left-width=5pt,
border-color=blue,
padding-left=1ex,
]This is a definition
\end{longfbox}
Strange colors .
This is a definition
Besides the regular CSS attributes, colors for borders around a page break are
set as:
border-break-color=⟨color break-sides⟩
border-break-top-color=⟨color⟩ (=black)
border-break-bottom-color=⟨color⟩ (=black)
8
border-dark-mix=⟨color mix⟩ (=!70!black)
The border-dark-mix is used to make a color darker and is used for the inset,
outset, groove and ridge styles. This value is basically appended to the main
color of the border. The default takes 70% of the main color and mixes in 30%
black.
border-radius=⟨radius corners⟩
border-top-left-radius=⟨radius⟩ (=0pt)
border-top-right-radius=⟨radius⟩ (=0pt)
border-bottom-left-radius=⟨radius⟩ (=0pt)
border-bottom-right-radius=⟨radius⟩ (=0pt)
The above attributes specify the corner radius to enable rounded corners.
⟨radius⟩=⟨dimen⟩ | {⟨x-radius⟩,⟨y-radius⟩}
\lfbox[border-radius=0.5ex]{rounded},
\lfbox[border-radius=100ex, background-color=floralwhite]{\strut elliptical},
\lfbox[border-radius=0.5em,height=1em,width=1em,tight,
text-align=center,height-align=middle]{1}.
rounded , elliptical , 1 .
9
\begin{longfbox}[
border-radius=15pt,
border-width=2pt,
border-top-left-radius={50pt,25pt},
border-right-style=dashed,
border-left-style=double,
border-left-color=teal,
padding={1em,15pt},
width=0.6\linewidth,
]
\hobbit[7]
\end{longfbox}
3.2. Alignment
Much care has been taken to ensure proper alignment and preservation of the
baseline. In our examples, we use the following definition where we enable
show-markers so we can see the baseline and dimensions of the longbox:
\newcommand\alignbox[1]{%
\begin{longfbox}[width=2em,height=4.25em,show-markers,
baseline-skip=false,#1]
foo,\\ bar,\\ gnu.
\end{longfbox}%
}
The baseline attribute is not a CSS attribute, but we can use it to control the
baseline of the content of a box. For example:
10
Aligning \alignbox{baseline=bottom},
\alignbox{baseline=middle},
\alignbox{baseline=top} done.
foo,
bar, foo,
Aligning gnu. , bar, , foo, done.
gnu. bar,
gnu.
The default baseline attribute aligns the baseline of the box with the baseline
of the text. The bottom attribute aligns the bottom of the box with the bottom
of the text, middle aligns the middle of the box with the middle of the text, and
top aligns the top of the box with the top of the text.
Here are the various attributes in action (compare this to the examples for
different baselines):
Aligning \alignbox{vertical-align=bottom},
\alignbox{vertical-align=middle},
\alignbox{vertical-align=top} done.
foo,
bar,
gnu. foo,
Aligning , bar, , foo, done.
gnu. bar,
gnu.
Finally, the super and sub attributes align the baseline of the box with the
baseline of super- and sub-scripts:
11
$x^x_x$ \alignbox{vertical-align=super}, \alignbox{vertical-align=sub} $x^x_x$.
foo,
foo,
bar,
bar,
xxx gnu. , x
gnu. xx .
raise=⟨dimen⟩
foo,
bar,
gnu. foo,
Aligning , bar, , done.
gnu.
This is another non-CSS attribute (but probably one of the most desired :-)):
it specifies the vertical alignment of the content inside the box. This attribute
only has an effect for boxes where the height is specified. This attribute keeps
the baseline unchanged and does not influence the vertical alignment directly.
12
Aligning \alignbox{height-align=bottom},
\alignbox{height-align=middle},
\alignbox{height-align=top},
\alignbox{height-align=middle,baseline=top},
done.
Specifies the alignment of the content horizontally. The default is left for a
horizontal \lfbox and justify for a longfbox environment.
And vertical
\alignbox{text-align=center,baseline=middle,width=4em} too.
Just like with \makebox we can use a narrow width to let the text overlay to the
left or right:
13
3.3. Background
background-color=⟨color⟩ (={})
background-clip=border-box | padding-box | content-box
\newcommand\bgbox[2]{%
\lfbox[rounded,border-style=double,border-width=3pt,
border-color=teal,
background-color=#1,background-clip=#2]%
}
a\rlap{b}\bgbox{teal!30}{border-box}{foo},
a\rlap{b}\bgbox{teal!30}{padding-box}{foo},
a\rlap{b}\bgbox{teal!30}{content-box}{foo}.
background-padding-color=⟨color⟩ (=\option{background-color})
background-border-color=⟨color⟩ (=\option{background-color})
background-content-color=⟨color⟩ (=\option{background-color})
Going beyond CSS, we can also specify the colors for the background at the
border and padding separately.
A \lfbox[rounded,
background-color=teal!30,
background-padding-color=floralwhite,
background-border-color=gray!50,
border-style=double,border-width=3pt
]{too colorful} box.
14
3.4. Padding and margins
padding=⟨padding sides⟩
padding-top=⟨dimen⟩ (=\fboxsep)
padding-right=⟨dimen⟩ (=\fboxsep)
padding-bottom=⟨dimen⟩ (=\fboxsep)
padding-left=⟨dimen⟩ (=\fboxsep)
The padding is the space between the content and the border of a box. By
default the padding is equal to the \fboxsep value.
margin=⟨margin sides⟩
margin-top=⟨dimen⟩ (=0pt)
margin-right=⟨dimen⟩ (=0pt)
margin-bottom=⟨dimen⟩ (=0pt)
margin-left=⟨dimen⟩ (=0pt)
The margin is the transparent area outside the borders. In contrast to the
CSS attribute, the margins do not overlap. Please use the standard \addvspace
command for adding overlapping top- and bottom-margins.
\begin{longfbox}[width=6.8em]
Here is a longer paragraph with a
\lfbox[margin={1em,0.5em,1em},padding=1ex,show-markers]{box}
inside with margins.
\end{longfbox}
Here is a longer
paragraph with
a box inside
with margins.
padding-break-top=⟨dimen⟩ (=0.5em)
padding-break-bottom=⟨dimen⟩ (=0.5em)
margin-break-top=⟨dimen⟩ (=0pt)
margin-break-bottom=⟨dimen⟩ (=0pt)
15
“Halt!” cried Gandalf, who appeared suddenly,
and stood alone, with arms uplifted, between
the advancing dwarves and the ranks awaiting
border-break-bottom-style
width,color padding-break-bottom
margin-break-bottom
margin-break-top
padding-break-top
them. “Halt!” he called in a voice like thun-
border-break-top-style
width,color
padding-break-top
der, and his staff blazed forth with a flash like
the lightning. “Dread has come upon you all!
Alas! it has come more swiftly than I guessed.”
Figure 2. A box that has been broken in three parts. The border style and
the padding and margin of each break can be set separately. Use the breakable
option to make boxes breakable over page boundaries. In the above example
we also used the breakat={75pt} option to break at specific heights, and the
background-clip=content-box to limit the background color to the content only.
These attributes determine the margin and padding around a page break. By
default, there is some padding set around a break such that the vertical borders
of a box ‘stick out’ a bit giving the reader a hint that the box continues at the
next page (see Figure 2)
breakable=⟨bool⟩ (=false)
extra-split=⟨dimen⟩ (=1.5\baselineskip)
(Advanced) This option determines the minimal height of a box that is broken.
16
If the height would be less the box is not broken and moved to the next page.
This prevents for example to have just the top border and padding on one page
followed by content on the next page.
breakat={⟨dimen1 ⟩,...,⟨dimenn ⟩}
(Advanced) This option lets you break a box manually at specific heights. The
breakable option must be set for this to work. Usually a box is broken to fit
the space available on the page, but when breakat is given, the box breaks at
⟨dimen1 ⟩. After the break, the first dimension is removed from the list and the
box is broken again at ⟨dimen2 ⟩ until only one element (⟨dimenn ⟩) is left. After
that the box is repeatedly broken at ⟨dimenn ⟩ until all content is processed. For
example, in Figure 2 we used breakat={75pt} to break the box at three 75pt
heights. Note that when a box breaks, it chooses the largest height that is less
than 75pt where the content can be broken nicely, i.e. a box never breaks in
the middle of a line for example.
The breakat can also be used to break a box in a multicols environment.
height=⟨dimen⟩
width=⟨dimen⟩
Specifies the height or width of the inner content box, see Figure 1. By default,
the width of horizontal \lfbox is the natural width of its content. In contrast,
the default width of a vertical longfbox environment is the current \linewidth.
The default height is always the natural height of the content. When the height
is fixed, you can use height-align to align the content in the available area.
outer-height=⟨dimen⟩
outer-width=⟨dimen⟩
For convenience, there are also these non-CSS attributes that let you specify the
width and height of the entire box including the padding, border, and margins.
Internally translated to the height or width before processing the box.
tight={padding=0pt,margin=0pt,padding-break=0pt}
rounded={border-radius=1ex}
17
dotted={border-width=0.8pt,border-style=dotted}
Some predefined convenient styles. tight puts the box tightly around the con-
tent. The rounded style uses a border radius that looks nice relative to the font
size, and dotted uses a slightly larger border width which looks better with dots.
A \lfbox[tight]{tight}, \lfbox[dotted]{dotted},
and \lfbox[rounded]{rounded} box.
4. Advanced topics
4.1. Hooks and rendering
There are two ways to render a box border: using just plain LATEX and the
LATEX picture environment. The plain renderer just uses \hrule etc. and can
only render simple boxes with solid or dashed styles without rounded corners.
The default will pick the plain renderer if a box is simple, and use the picture
renderer otherwise. This is mostly to make the rendering more efficient but
there should be no other difference.
insert-before=⟨value⟩
insert-after=⟨value⟩
These are hooks to insert content just before or after the content box.
A \lfbox[insert-before={“\bgroup\itshape},
insert-after={\/\egroup”}]{quoted}
box.
A “quoted” box.
render-insert-before=⟨value⟩
render-insert-after=⟨value⟩
18
These are hooks to insert content just before or after the border-box is rendered.
\newcommand\makecircle{%
\setlength\unitlength{1pt}%
\begin{picture}(0,0)% make it occupy no space
\color{red}%
\put(0,0){\circle*{5}}%
\end{picture}%
}
\lfbox[render-insert-before=\makecircle]{funny}.
funny .
picture-insert-before=⟨value⟩
picture-insert-after=⟨value⟩
These insert content just before or after rendering the frame in a picture en-
vironment. In both case, the origin is at the bottom-right corner. Here is an
example where we cross-out a box:
\newcommand\crossout{%
\color{red}\linethickness{1pt}\roundcap%
\moveto(0,0)
\lineto(\optionunit{/fbox/@border-box-width},
\optionunit{/fbox/@border-box-height})
\strokepath
}
This is
\lfbox[rounded,picture-insert-after=\crossout]{crossed out}.
plain-side-insert-before=⟨value⟩
plain-side-insert-after=⟨value⟩
picture-side-insert-before=⟨value⟩
picture-side-insert-after=⟨value⟩
19
4.2. Internal attributes
baseline-skip=⟨bool⟩ (=true)
Usually, the library adds a small vertical skip in front of a vertical longfbox
such that it content aligns to a \baselineskip. Similarly, it adds such skip just
after the box. This generally makes text align better, especially on a double
column layout. Setting it to false disables such vertical spacing.
show-markers=⟨bool⟩
marker-color=⟨color⟩ (=gray)
marker-width=⟨dimen⟩ (=0.1pt)
If show-markers is true it will show the padding, baseline, margin and border
markers using marker-color and marker-width.
eject=⟨value⟩ (={\protect\vfill\protect\eject})
After breaking a box, this command is issued which normally ends the current
page. The breakat command sets this to empty so no page break occurs in that
case.
debug=⟨bool⟩ (=false)
verbose=⟨bool⟩ (=false)
border-dash=⟨dash sides⟩
border-top-dash=⟨dimen⟩ (=0.7ex)
border-right-dash=⟨dimen⟩ (=0.7ex)
border-bottom-dash=⟨dimen⟩ (=0.7ex)
border-left-dash=⟨dimen⟩ (=0.7ex)
border-break-top-dash=⟨dimen⟩ (=\option{border-top-dash})
border-break-bottom-dash=⟨dimen⟩ (=\option{border-bottom-dash})
20
border-dashskip=⟨dashskip sides⟩
border-top-dashskip=⟨dimen⟩ (=0.7\option{border-top-dash})
border-right-dashskip=⟨dimen⟩ (=0.7\option{border-right-dash})
border-bottom-dashskip=⟨dimen⟩ (=0.7\option{border-bottom-dash})
border-left-dashskip=⟨dimen⟩ (=0.7\option{border-left-dash})
border-break-top-dashskip=⟨dimen⟩ (=\option{border-top-dashskip})
border-break-bottom-dashskip=⟨dimen⟩ (=\option{border-bottom-dashskip})
border-dotskip=⟨dotskip sides⟩
border-top-dotskip=⟨dimen⟩ (=0.7\option{border-top-width})
border-right-dotskip=⟨dimen⟩ (=0.7\option{border-right-width})
border-bottom-dotskip=⟨dimen⟩ (=0.7\option{border-bottom-width})
border-left-dotskip=⟨dimen⟩ (=0.7\option{border-left-width})
border-break-top-dotskip=⟨dimen⟩ (=\option{border-top-dotskip})
border-break-bottom-dotskip=⟨dimen⟩ (=\option{border-bottom-dotskip})
21