LaTeX 的 tcolorbox 宏包是最常见的盒子样式美化宏包,在各个模板中都广泛使用,tcolorbox 宏包的功能非常复杂丰富,文档长达五百多页,还可以深度结合 tikz 得到更丰富的样式。下面简单记录一下 tcolorbox 最基础的一些用法,这里使用 lipsum 宏包生成对应的填充文本。

tcolorbox 宏包的功能模块化,可以按需进行导入,为了使用方便,可以直接加上 [most] 选项

1
\usepackage[most]{tcolorbox}

首先从 tcolorbox 环境开始,用法如下

1
2
3
\begin{tcolorbox}[<options>]
\lipsum[1][1-3]
\end{tcolorbox}

可以通过可选参数来设置盒子的样式,最基础的选项包括:

  • colback: 背景色
  • colframe: 边框色
  • title:盒子标题

注意:

  • 不设置任何选项则会使用默认样式;
  • 如果出现重复选项,不会报错,后者会对前者进行覆盖。

例如

1
2
3
4
5
6
7
\begin{tcolorbox}
\lipsum[1][1-3]
\end{tcolorbox}

\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black,title={My title}]
\lipsum[2][1-3]
\end{tcolorbox}

可以通过 \tcbset 命令设置 tcolorbox 的默认样式,对后续的所有盒子生效,例如

1
\tcbset{colback=red!5!white,colframe=red!75!black}

还可以在 \tcbset 命令中定义预设样式,然后就可以在样式选项中用 myboxstyle 替代,例如

1
2
3
4
5
6
7
8
9
\tcbset{
myboxstyle/.style={
colback=yellow!20!white,
colframe=yellow!70!black}
}

\begin{tcolorbox}[myboxstyle]
\lipsum[3][1-3]
\end{tcolorbox}

这三个盒子的效果如下图(第一个是默认样式)

除了直接使用 tcolorbox 环境,还可以使用 \newtcolorbox 命令生成新的 tcolorbox 环境,作用相当于 \newenvironment 命令。

1
\newtcolorbox[<init options>]{<name>}[<number>][<default>]{<options>}

例如一个不含参数的新环境

1
2
3
4
5
\newtcolorbox{mybox1}{colback=red!5!white,colframe=red!75!black}

\begin{mybox1}
\lipsum[1][1-3]
\end{mybox1}

一个带必选 title 参数的新环境

1
2
3
4
5
6
7
\newtcolorbox{mybox2}[1]{colback=red!5!white,
colframe=red!75!black,fonttitle=\bfseries,
title={#1}}

\begin{mybox2}{My Box Title}
\lipsum[2][1-3]
\end{mybox2}

一个带可选 title 参数的新环境

1
2
3
4
5
6
7
8
9
10
11
\newtcolorbox{mybox3}[1][]{colback=red!5!white,
colframe=red!75!black,fonttitle=\bfseries,
title={Note\ifx\relax#1\relax\else: #1\fi}}

\begin{mybox3}[My Box Title]
\lipsum[3][1-3]
\end{mybox3}

\begin{mybox3} % no title
\lipsum[4][1-3]
\end{mybox3}

这四个盒子的效果如下图

可以将新环境接收的选项继续传递给 tcolorbox,达到允许临时修改样式的目的,例如

1
2
3
4
5
6
7
8
9
\newtcolorbox{cbox}[1][]{%
enhanced,
breakable,
sharp corners,
leftrule=2pt, rightrule=0pt, toprule=0pt, bottomrule=0pt,
colframe=SkyBlue,
colback=SkyBlue!8,
#1
}

可以在 \newtcolorbox 命令的 init options 设置编号规则,在 options 中通过 \thetcbcounter 获取编号,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
\section{Demo}

\newtcolorbox[auto counter,number within=section]{cntbox}[1][]{colback=red!5!white,
colframe=red!75!black,fonttitle=\bfseries,
title={Note~\thetcbcounter\ifx\relax#1\relax\else: #1\fi}}

\begin{cntbox}[My Box Title]
\lipsum[1][1-3]
\end{cntbox}

\begin{cntbox}
\lipsum[2][1-3]
\end{cntbox}

除了 \newtcolorbox 命令,还可以使用 \renewtcolorbox 命令重新定义现有环境。

考虑一些更复杂的样式,需要设置更多的选项:

  • enhanced:支持更复杂的样式(否则部分样式选项无效),但是会降低编译效率
  • breakable:支持分页
  • fonttitle:标题字体
  • frame hidden:隐藏边框
  • boxrule=1pt:边框宽度
  • leftrule=2pt, rightrule=0pt, toprule=0pt, bottomrule=0pt:分别指定每一个方向的边框宽度
  • rounded corners / sharp corners:圆角 / 直角边框(默认圆角)
  • drop shadow={black!50!white}:生成盒子阴影

例一

1
2
3
4
5
6
7
8
9
\begin{tcolorbox}[
enhanced,
breakable,
sharp corners,
leftrule=2pt, rightrule=0pt, toprule=0pt, bottomrule=0pt,
colframe=SkyBlue,
colback=SkyBlue!8]
\lipsum[1][1-3]
\end{tcolorbox}

例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
\begin{tcolorbox}[
enhanced,
breakable,
colback=orange!2,
frame hidden,
overlay={
\draw[orange!75, line width=2pt]
(frame.north west) -- ++(3mm,0)
(frame.north west) -- ++(0,-3mm)
(frame.south east) -- ++(-3mm,0)
(frame.south east) -- ++(0,3mm);
}]
\lipsum[2][1-3]
\end{tcolorbox}

例三

1
2
3
4
5
6
7
8
9
10
11
\begin{tcolorbox}[
enhanced,
breakable,
colframe=SkyBlue,
colback=SkyBlue!8,
title={Note},
fonttitle=\bfseries,
attach boxed title to top left={xshift=4mm,yshift=-2mm},
boxed title style={size=small,colback=SkyBlue!80!black}]
\lipsum[3][1-3]
\end{tcolorbox}

例四

1
2
3
4
5
6
7
8
9
10
11
12
13
\begin{tcolorbox}[
enhanced,
breakable,
sharp corners,
colback=yellow!20!white,
colframe=yellow!70!black,
drop shadow={black!50!white},
title={Note},
fonttitle=\bfseries\color{black},
attach boxed title to top left={xshift=-2mm,yshift=-2mm},
boxed title style={size=small,colback=yellow!80!black,colframe=yellow!70!black}]
\lipsum[4][1-3]
\end{tcolorbox}

例五

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
\begin{tcolorbox}[
enhanced,
before skip=2mm,after skip=3mm,fontupper=\sffamily,
boxrule=0.4pt,left=5mm,right=2mm,top=1mm,bottom=1mm,
colback=yellow!50,
colframe=yellow!20!black,
sharp corners,rounded corners=southeast,arc is angular,arc=3mm,
underlay={%
\path[fill=tcbcolback!80!black] ([yshift=3mm]interior.south east)--++(-0.4,-0.1)--++(0.1,-0.2);
\path[draw=tcbcolframe,shorten <=-0.05mm,shorten >=-0.05mm] ([yshift=3mm]interior.south east)--++(-0.4,-0.1)--++(0.1,-0.2);
\path[fill=yellow!50!black,draw=none] (interior.south west) rectangle node[white]{\Huge\bfseries !} ([xshift=4mm]interior.north west);
},
drop fuzzy shadow]
\lipsum[1][1-2]
\end{tcolorbox}

通过\newtcolorbox 命令将这些样式封装为新环境也是容易的。

例如基于第一个样式,定义一个可以接收参数以调整盒子样式的新环境 cbox

1
2
3
4
5
6
7
8
9
\newtcolorbox{cbox}[1][]{%
enhanced,
breakable,
sharp corners,
leftrule=2pt, rightrule=0pt, toprule=0pt, bottomrule=0pt,
colframe=SkyBlue,
colback=SkyBlue!8,
#1
}

基于第二个样式,定义一个适合引用原文的新环境 cboxquote

1
2
3
4
5
6
7
8
9
10
11
12
13
\newtcolorbox{cboxquote}{
colback=orange!2,
enhanced,
breakable,
frame hidden,
overlay={
\draw[orange!75, line width=2pt]
(frame.north west) -- ++(3mm,0)
(frame.north west) -- ++(0,-3mm)
(frame.south east) -- ++(-3mm,0)
(frame.south east) -- ++(0,3mm);
}
}

基于第三个样式,定义一个支持可选标题的新环境 tbox

1
2
3
4
5
6
7
8
9
10
\newtcolorbox{tbox}[1][]{
enhanced,
breakable,
colframe=SkyBlue,
colback=SkyBlue!8,
title={#1},
fonttitle=\bfseries,
attach boxed title to top left={xshift=4mm,yshift=-2mm},
boxed title style={size=small,colback=SkyBlue!80!black},
}

基于第四个样式,定义支持可选标题的便利贴样式的新环境 notebox/notebox*,分别带编号和不带编号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
\tcbset{
noteboxstyle/.style={
enhanced,
breakable,
sharp corners,
colback=yellow!20!white,
colframe=yellow!70!black,
drop shadow={black!50!white},
fonttitle=\bfseries\color{black},
attach boxed title to top left={xshift=-2mm,yshift=-2mm},
boxed title style={size=small,colback=yellow!80!black,colframe=yellow!70!black}}
}

\newtcolorbox[auto counter, number within=section]{notebox}[1][]{
noteboxstyle, title={Note~\thetcbcounter\ifx\relax#1\relax\else: #1\fi}
}
\newtcolorbox{notebox*}[1][]{
noteboxstyle, title={Note\ifx\relax#1\relax\else: #1\fi}
}

通过 \tcolorboxenvironment 命令可以用 tcolorbox 环境封装已有的环境,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
\declaretheorem[style=plain, name=Theorem, numbered=yes, numberwithin=section]{theorem}
\declaretheorem[style=plain, name=Theorem, numbered=no]{theorem*}

\tcolorboxenvironment{theorem}{
enhanced,
breakable,
sharp corners,
leftrule=2pt, rightrule=0pt, toprule=0pt, bottomrule=0pt,
colframe=RoyalPurple,
colback=RoyalPurple!8
}
\tcolorboxenvironment{theorem*}{
enhanced,
breakable,
rounded corners,
leftrule=2pt, rightrule=0pt, toprule=0pt, bottomrule=0pt,
colframe=RoyalPurple,
colback=RoyalPurple!8
}

补充几个用过的样式:适合用在盒子中的分割虚线

1
2
3
\newcommand{\tboxdash}{
\tikz{\draw[densely dashed, color=SkyBlue!70!black, line width=0.8pt] (2mm,0)--(\linewidth-2mm,0);}
}

inline 盒子

1
2
3
4
\newtcbox{\inlinebox}[1][purple]{
on line, colback=#1!10!white,
boxsep=0pt,left=2pt,right=2pt,top=3pt,bottom=3pt,boxrule=0.2pt
}

效果如下

对应完整源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
\documentclass{article}
\usepackage[dvipsnames]{xcolor}
\usepackage{lipsum}
\usepackage[most]{tcolorbox}

\newtcolorbox{tbox}[1][]{
enhanced,
breakable,
colframe=SkyBlue,
colback=SkyBlue!8,
title={#1},
fonttitle=\bfseries,
attach boxed title to top left={xshift=4mm,yshift=-2mm},
boxed title style={size=small,colback=SkyBlue!80!black},
}

\newcommand{\tboxdash}{
\tikz{\draw[densely dashed, color=SkyBlue!70!black, line width=0.8pt] (2mm,0)--(\linewidth-2mm,0);}
}

\newtcbox{\inlinebox}[1][purple]{
on line, colback=#1!10!white,
boxsep=0pt,left=2pt,right=2pt,top=3pt,bottom=3pt,boxrule=0.2pt
}

\begin{document}

\begin{tbox}[Hello]
\lipsum[2]

\tboxdash

\lipsum[3][1-3]

Hello, this is an \inlinebox[Red]{inline box} example.

\tboxdash

\lipsum[4][1]
\end{tbox}

\end{document}

tcolorbox 经常会因为无法对盒子进行合适的分页而给出警告

1
Package tcolorbox: Using nobreak failed. Try to enlarge lines before break' or set page breaks manually.

可以用 silence 宏包来忽略对应的警告。

1
2
\usepackage{silence}
\WarningFilter{tcolorbox}{Using nobreak failed}