LaTeXで作った数学ノートでは、独自に実装したさまざまな囲みボックスを利用しています。

そのほとんどはtcolorboxをベースに実装しており、私自身がtcolorboxへの理解を深める作業も兼ねて、その実装を振り返るブログを書きたいと思います。

今回から数回にわたって、tcolorboxの機能について掘り下げながら、さまざまな事例を紹介していきます。

tcolorboxとは何か

LaTeXでは、TikZという多機能な描画パッケージを利用することができます。(これが私がLaTeXをやめられない理由の一つです。)

TikZの機能を駆使すれば、さまざまな図版や装飾が実現可能です。
しかし、あまりに多機能なので、すべての機能を把握する学習コストは高く、また、TikZで1から構築するのは面倒なものもやはりあります。

そこで、よく使われるユースケースについては、より簡単なコードで実現できるようなTikZ派生パッケージが世に多く存在しています。
その中でも、カスタマイズ可能な囲みボックスを提供するパッケージがtcolorboxです。

tcolorboxの強力さに立ち向かう

tcolorboxの強力さを物語る記事はすでにたくさんあります!
たとえば、次のブログで紹介されている作例は筆者の憧れです。

tcolorboxによるカスタム囲みボックスの実装は、最終的には公式ドキュメントを参照しながら進めることになりますが、何もわからないまま500ページを超えるドキュメントを探索するのは苦行です。

そこで今回は、最初に知っておくとスムーズに入門できる、基本的な概念や機能に焦点を当てて解説します。主に取り上げる内容は次の通りです。

  • tcolorboxの基本的な使い方(Hello, tcolorbox!)
  • カスタム実装を始める前に知っておきたい仕組み
    • skinsライブラリによる描画方式の切り替え
    • tcolorboxにおける余白の種類と設定
  • カスタム実装の第一歩
    • デフォルトスタイルのリセット

Hello, tcolorbox!

プリアンブルに次のように書くことで、tcolorboxを使い始めることができます。

\usepackage{tcolorbox}

tcolorbox環境の基本

tcolorboxパッケージは、囲み枠付きでコンテンツを描画するtcolorbox環境を提供します。

\begin{tcolorbox}[オプション]
  囲みたい内容
\end{tcolorbox}

LaTeXのコマンドや環境において、[]で囲まれた部分は指定してもしなくてもいい引数です。
そのため、次のように[オプション]の部分は省略してtcolorbox環境を使うことができます。

\begin{tcolorbox}
  こんにちは世界
\end{tcolorbox}

このコードは次のように描画されます。オプションを何も指定しなかった場合は、デフォルトのスタイル(黒い枠線にグレーの背景)が適用されるのです。

タイトルをつけたり、スタイルをカスタマイズしたりしたい場合には、[]の中にさまざまなオプションを指定していきます。これがtcolorbox環境の基本的な使い方です。

ライブラリの読み込み

また、指定するオプションによっては、tcolorboxが提供するライブラリの読み込みが必要です。
ライブラリの読み込みは、次のようにプリアンブルで指定します。

\usepackage{tcolorbox}
\tcbuselibrary{ライブラリ名}

この時点で、どんなオプションやライブラリがあるのか、どのようなことができるのか、探索してみたい方には次の記事がおすすめです。

このシリーズでは、さまざまな囲みボックスの実例を取り上げる中で、必要なオプションやライブラリを都度紹介していくことにします。

補足:ダミーテキストによる表示確認

独自の囲みボックスを実装するときには、さまざまな長さの文章で表示を確認してみるとよいでしょう。

短い文章では気にならなかった余白の狭さなどが、複数行になると目立つようなことはよくあります。
また、ページをまたぐほど長い文章を入れたときの挙動はどうなるのか?など、文章の長さを変えながら表示を確認・調整することはとても大切です。

このような試作段階では、ダミーテキストを任意の長さで出力する\lipsumコマンドを使うと便利です。
プリアンブルに次の指定を加えることで、\lipsumコマンドが使えるようになります。

\usepackage{lipsum}

\lipsumコマンドでは、引数を指定することで、生成する文章の長さを簡単に変えることができます。
たとえば、\lipsum[1][1-2]と指定した場合は、Lorem ipsumの第1段落の第1文と第2文が出力されます。

\begin{tcolorbox}
  \lipsum[1][1-2]
\end{tcolorbox}

今後、このシリーズで示すデモコードでも、\lipsumコマンドによるダミーテキストを利用していきます。引数のさまざまな指定や省略については、次のサイトでわかりやすく解説されているので、参考にしてみてください。

適切な描画方式を選ぶ(skinsライブラリ)

tcolorboxは、「どの描画エンジンを使うか」「どのようなスタイルを有効化するか」などの描画方式を、skinという仕組みで管理しています。

囲みボックスをカスタマイズするときには、デザインの複雑さや使いたい機能に応じてskinを使い分ける必要があります。
よく使うskinとして、emptyenhanceddraftを覚えておくと便利です。

  • empty:何も描かないようにする(デフォルトスタイルのリセットに使う)
  • enhanced:TikZによる高度な描画機能を有効化する(カスタマイズ時にはほぼ必須)
  • draft:ボックスの寸法やボックス内余白を可視化する(デバッグ用)

これらのskinへの切り替えはskinsライブラリによって可能になるため、プリアンブルに次の指定を加えた上でカスタマイズを行うことがほとんどです。

\tcbuselibrary{skins}

tcolorboxの余白を理解する

tcolorboxでは、ボックスの余白の大きさや枠線の太さなどを細かく指定することができます。
細かいカスタマイズが可能な分、余白の設定だけでも数多くのオプションが用意されており、ドキュメントから自分の意図に合うオプションを探し出すのは大変な作業です。

まずは余白の種類をざっくりと把握しておくことで、ドキュメントの読解や実装がスムーズになります。

公式ドキュメントにも、余白の種類が図で一覧化されている「Quick Reference」という章があり、とても便利です。
この記事では、その中でも特によく使うオプションに絞って概観しておきたいと思います。

ボックスの内側の余白と枠線の太さ

枠線の太さは、上下左右に対応する~ruleオプションでそれぞれ指定します。

  • toprule/bottomrule
  • leftrule/rightrule

ボックスの内側の余白を制御するコマンドには、次のようなものがあります。

  • boxsep
  • top/bottom/left/right

boxsepは、ボックスの中身と枠の間に、共通のパディング(余白)を設定するオプションです。
boxsepでベースとなる余白を指定したら、さらにleftrighttopbottomオプションで上下左右の余白を個別に加算するという使い方をします。

draft skinによる余白の可視化

さて、これらのオプションを指定した結果、どのようにボックス内の余白や枠線の幅が確保されるかは、draftskinを使うことで視覚的に確認できます。実際にやってみましょう。

次のようなオプション群を、myspacingという名前で使い回せるように定義しておきます。

\tcbset{
  myspacing/.style={
    sharp corners, % 角丸を無効化する
    toprule=0.5em, bottomrule=0.5em,
    leftrule=0.5em, rightrule=0.5em,
    boxsep=1em,
    top=2em, bottom=2em,
    left=2em, right=2em,
  }
}

\tcbsetコマンドは、コマンド呼び出し箇所以降に登場するすべてのtcolorbox環境に対してグローバルにオプションを設定したり、特定のデザインを実現するオプション群に名前をつけたりするためのコマンドです。

上のように定義しておくと、tcolorbox環境のオプションにmyspacingと指定するだけで、myspacing/.style={}内で指定したスタイルオプションをすべてまとめて設定することができます。

% \tcbuselibrary{skins} が必要
\begin{tcolorbox}[myspacing]
  \lipsum[1][1-5]
\end{tcolorbox}

ここでさらに、draftオプションを追加してdraftskinに切り替えると、ボックス内余白や枠線の内訳とその寸法を視覚化するデバッグ用の表示に切り替わります。

% \tcbuselibrary{skins} が必要
\begin{tcolorbox}[myspacing, draft]
  \lipsum[1][1-5]
\end{tcolorbox}

中央の緑色の領域は、ボックス内のコンテンツが占める領域です。
その外側の白い領域がboxsepによる余白、さらにその外側のピンク色の領域がleftrighttopbottomによる余白、グレーの領域が枠線の幅を示しています。

draftオプションを指定していない通常の表示と見比べると、通常の表示では、グレーの領域に枠線の色が適用され、グレーより内側の領域すべて(ピンク色の領域、白い領域、緑色の領域)に背景色が適用されることがわかります。

ボックスの上下の余白(skipオプション)

ボックスの外側、特に上下の余白は、ボックスとその前後の段落との間隔を制御する上で重要です。
それぞれ、次のオプションで指定します。

  • before skip:ボックスの上の余白(前の段落との間隔)
  • after skip:ボックスの下の余白(次の段落との間隔)
  • beforeafter skip:ボックスの上下の余白(まとめて同じサイズに設定)

発展:skipとskip balancedの使い分け

また、これらと似たオプションとして、before skip balancedafter skip balancedbeforeafter skip balancedというオプションも用意されています。

balancedの有無による違いを明らかにするために、0ptを指定した場合を比較してみます。

before skipの場合
Text without descenders.
\begin{tcolorbox}[before skip=0pt]
  \texttt{before skip=0pt}
\end{tcolorbox}
 
\lipsum[1][1]
\begin{tcolorbox}[before skip=0pt]
  \texttt{before skip=0pt}
\end{tcolorbox}

before skip=0ptを指定した場合は、ボックスの前のテキストの文字の下端が、ボックスの上辺にべったりくっついてしまいます。0ptを指定したことで、完全に間隔が0になっているのです。

また、1つめのボックスではすべての文字の下端がべったりとボックスに接していますが、2つめのボックスではpgなどの文字だけがボックスに接しているため、他の文字は少し浮いて見えます。
これにより、テキストとボックスの間の余白がばらついて見えてしまいます。実際、頭文字に注目すると、1つめのボックスとTの間より、2つめのボックスとLの間の方が少し空いて見えるはずです。

一方、before skip balanced=0ptを指定した場合は、0ptを指定しているにもかかわらず、少しテキストとボックスの間隔にゆとりが生まれます。
そして、pgなどの下にはみ出す文字の有無に関わらず、テキストとボックスの間の余白が一定に見えるように自動調整されるため、こちらの方が自然に美しく見えるのではないでしょうか。

before skip balancedの場合
Text without descenders.
\begin{tcolorbox}[before skip balanced=0pt]
  \texttt{before skip balanced=0pt}
\end{tcolorbox}
 
\lipsum[1][1]
\begin{tcolorbox}[before skip balanced=0pt]
  \texttt{before skip balanced=0pt}
\end{tcolorbox}

この実験から、次のような使い分けができそうです。

  • 厳密に間隔を制御したいときは~ skipを使う
  • 自然な行間バランスを保ちたいときは~ skip balancedを使う

デフォルトスタイルのリセット

囲みボックスをカスタマイズするときには、まずはデフォルトのスタイルを消してから、独自にスタイルを設定し直すことがよくあります。

デフォルトのスタイルのうち、何をリセットしたいかによって、オプションやskinを使い分けます。

\lipsum[1][1-2]
 
\begin{tcolorbox}
  こんにちは世界(\texttt{default}
\end{tcolorbox}
 
\lipsum[1][3-4]
 
\begin{tcolorbox}[enhanced, frame hidden]
  こんにちは世界(\texttt{enhanced, frame hidden}
\end{tcolorbox}
 
\lipsum[1][5-6]
 
\begin{tcolorbox}[empty]
  こんにちは世界(\texttt{empty}
\end{tcolorbox}
 
\lipsum[2][1-2]
 
\begin{tcolorbox}[size=minimal]
  こんにちは世界(\texttt{size=minimal}
\end{tcolorbox}
 
\lipsum[2][3-4]

余白をリセット

size=minimalを指定することで、デフォルトの余白をすべて消すことができます。

\begin{tcolorbox}[size=minimal]
  こんにちは世界
\end{tcolorbox}

枠線や背景などのすべての装飾をリセット

枠線や背景色など、デフォルトの装飾をすべて消すには、「何も描かない」描画方式(skin)に切り替えるためのemptyオプションを指定します。

% \tcbuselibrary{skins} が必要
\begin{tcolorbox}[empty]
  こんにちは世界
\end{tcolorbox}

枠線だけを消す

枠線だけを消したい場合は、frame hiddenオプションを指定します。
このように描画の一部に手を加える場合は、enhancedオプションでskinを切り替えておく必要があります。

% \tcbuselibrary{skins} が必要
\begin{tcolorbox}[enhanced, frame hidden]
  こんにちは世界
\end{tcolorbox}

なお、背景色だけを消したい場合は、interior hiddenを指定します。

frame hiddeninterior hiddenを両方指定すると、見た目としてはemptyを指定した場合と同じになりますが、emptyenhancedでは使える機能が異なるため、必要に応じて使い分けていきます。

Next Step

tcolorboxの基本:カスタムボックスの実装

Deep Dive