\tcbset のスコープ(あるいはどうすれば tcolorbox の内部で局所化できるか)
tcolorbox に対する大域的な設定には \tcbset
を使う。ここで「大域的」というのは、厳密には「TeXのグループ」を指す。なので、\begingroup...\endgroup
で囲めば局所的な変更に使える。
しかし、「tcolorboxの中でさらに内側のtcolorboxを設定する」という使い方はできない。それどころか、外側の \tcbset
も無視される。
\tcbset{colbacktitle=red}
\begin{tcolorbox}[title=タイトルの背景は赤]
\tcbset{coltitle=white, colbacktitle=blue}
\begin{tcolorbox}[title=内側はタイトルの背景が青になってほしいな]
本文
\end{tcolorbox}
\end{tcolorbox}
入れ子の \tcbset
は効いてないし、外側の \tcbset
すら効いてない。つまり、tcolorbox は「TeXのグループ」を作るわけではないことがわかる。(ほんと?)
実は、入れ子の tcolorbox は「レイヤ」という概念で制御されている。レイヤについて詳しくは tcolorbox のマニュアル(Ver.6.2.0版では「4.16 Layered Boxes and Every Box Settings」)を参照。
tcolorbox の中でも \tcbset
を効かせるためには、全レイヤに適用させるバージョンの \tcbsetforeverylayer
というのがあるので、そっちを使う。
\tcbset{colbacktitle=red}
\begin{tcolorbox}[title=タイトルの背景は赤]
\tcbsetforeverylayer{coltitle=white, colbacktitle=blue}
\begin{tcolorbox}[title=内側はタイトルの背景が青になる]
本文
\end{tcolorbox}
\end{tcolorbox}
これでめでたしめでたしならいいんだけど、まだ罠がある。それは tcolorbox のタイトルを「Boxed Title」で作っている場合。Boxed Title 自体がレイヤなので、たとえばこんなふうにすると、すべてのレイヤにtitleを適用しようとして無限ループが起きてしまう。
\tcbset{colbacktitle=red}
\begin{tcolorbox}[title=タイトルの背景は赤]
\tcbsetforeverylayer{
enhanced, attach boxed title to top,
title=Boxed Titleという仕組みで付けたタイトル
}
\begin{tcolorbox}
本文
\end{tcolorbox}
\end{tcolorbox}
title
属性を局所的に記述するようにすれば実行は終了して結果が得られる。
\tcbset{colbacktitle=red}
\begin{tcolorbox}[title=タイトルの背景は赤]
\begingroup
\tcbsetforeverylayer{enhanced, attach boxed title to top}
\begin{tcolorbox}[title=Boxed Titleという仕組みで付けたタイトル]
本文
\end{tcolorbox}
\endgroup
\end{tcolorbox}
しかし、実は次のような書き方をしても通る。どうやら title
とBoxed Titleの設定を同時に適用しようとすると無限ループになるらしい。
\tcbset{colbacktitle=red}
\begin{tcolorbox}[title=タイトルの背景は赤]
\tcbsetforeverylayer{title=Boxed Titleという仕組みで付けたタイトル}
\begin{tcolorbox}[enhanced, attach boxed title to top]
本文
\end{tcolorbox}
\end{tcolorbox}
ところが、これは通りはするのだけど、出力結果はびっくりするものになる。
おそらく、Boxed Title自体がまたレイヤにより実現していて、\tcbsetforeverylayer
で設定した title
が再帰的に適用されてしまうのだろう。
では、\tcbset
や \tcbsetforeverylayer
を使って(つまりtcolorboxへの引数としてではなく)、Boxed Titleにタイトル文字列を設定することはできないのだろうか?
実はできる。\tcbset
には適用されるレイヤを細かく指定する機能があり、それを利用すれば、再帰的に適用されてタイトルが重複することなく、Boxed Titleのタイトル文字列を \tcbset
で設定できる。
\tcbset{colbacktitle=red}
\begin{tcolorbox}[title=タイトルの背景は赤]
\tcbset{every box on layer 2/.style={title=Boxed Titleという仕組みで付けたタイトル}}
\begin{tcolorbox}[enhanced, attach boxed title to top]
本文
\end{tcolorbox}
\end{tcolorbox}
every box on layer 2
という指定により、この設定を2つめのレイヤのみに制限している。「Boxed Titleの仕組みでタイトルの見た目を作りこんだtcolorboxを動的に生成するLaTeXコマンド」のようなものが必要で、しかもそれを別のtcolorboxの中でも使えるようにしたいという場合は、この仕掛けを使う必要があるだろう。
Discussion