10 tcolorbox 实现某种特定的边框

发布于 2025-05-03 12:10:05

目前 MWE 如下:

% !TEX program = pdflatex
\documentclass[a4paper, twoside]{book}

% basic layout
\usepackage[fontsize=12pt]{fontsize}
\usepackage[margin=1in]{geometry}
\usepackage{mathpazo}
\usepackage[explicit]{titlesec}
\usepackage[extramarks]{titleps}
\usepackage{titletoc}

\usepackage{indentfirst}

% graphics
\usepackage{xcolor}
\usepackage{graphicx}
\usepackage[most]{tcolorbox}
\usepackage{adjustbox}
\usepackage{wallpaper}

\definecolor{tianyi}{HTML}{66CCFF}
\definecolor{yanhe}{HTML}{00FFCC}
\definecolor{ling}{HTML}{EE0000}
\definecolor{qingxian}{HTML}{FFFF00}
\definecolor{skyblue}{HTML}{aeeafa}
\definecolor{darkblue}{RGB}{60,0,180}

\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}

% math typesetting
\usepackage{amsmath, amsthm, amssymb, bm}

\newtheoremstyle{definition}
    {\topsep}
    {\topsep}
    {\normalfont}
    {0pt}
    {\bfseries}
    {}
    {5pt plus 1pt minus 1pt}
    {}
\theoremstyle{definition}
\newtheorem{definition}{Definition}

\begin{document}

\begin{definition}[Vectors]
    This is a vector.
\end{definition}

\end{document}

希望实现如下图的效果:

image.png

即:

  1. 左、右、下边框完全绘制
  2. 上边框仅绘制两端长度为 3 em (可调整)的部分,中间插入 title。

查看更多

关注者
0
被浏览
233
Sagittarius Rover
我要成为Typst糕手/(ㄒoㄒ)/~~

刚看文档抄的... maybe related link by 鱼老师

\documentclass[a4paper,twoside,12pt,openany]{ctexbook}
\usepackage[margin=1in]{geometry}
\usepackage{tikz}
\usepackage[most]{tcolorbox}
\definecolor{tianyi}{HTML}{66CCFF}
\definecolor{yanhe}{HTML}{00FFCC}
\definecolor{ling}{HTML}{EE0000}
\definecolor{qingxian}{HTML}{FFFF00}
\definecolor{skyblue}{HTML}{aeeafa}
\definecolor{darkblue}{RGB}{60,0,180}
% math typesetting
\usepackage{amsmath,amsthm,amssymb}
\usepackage{lipsum,zhlipsum}
\begin{document}

\NewTColorBox[auto counter,number within=chapter]{mytcbbox}{O{black}m}{
    enhanced jigsaw,breakable,colframe=#1,top=2ex,boxrule=2pt,toprule=0pt,fonttitle=\large\bfseries,colback=white,sharp corners,attach boxed title to top left={xshift=3em,yshift=-\tcboxedtitleheight/2},coltitle=#1,title={Definition\thetcbcounter~#2},
    boxed title style={%
        empty,left=1pt,right=1pt,bottom=0pt,sharp corners,
        overlay={%
            \draw[color=#1,line width=2pt,line cap=round]
            ([yshift=-1pt]frame.west)--
            ++(-2.9em,0) ([yshift=-1pt]frame.east)--
            ++(3em,0);
        }
    },
}

\chapter{chap1}
\begin{mytcbbox}{My Def Title}
    \lipsum[2]
\end{mytcbbox}

\begin{mytcbbox}[qingxian]{My Def Title}
    \lipsum[1]
\end{mytcbbox}

\begin{mytcbbox}[tianyi]{My Def Title}
    I can eat the glass band it doesn't hurt me. I can eat the glass band it doesn't hurt me. I can eat the glass band it doesn't hurt me.
\end{mytcbbox}

\chapter{chap2}
\begin{mytcbbox}[yanhe]{My Def Title}
    我能吞下玻璃而不伤身体. 我能吞下玻璃而不伤身体. 我能吞下玻璃而不伤身体. 我能吞下玻璃而不伤身体. 我能吞下玻璃而不伤身体. 我能吞下玻璃而不伤身体. 
\end{mytcbbox}

\begin{mytcbbox}[darkblue]{My Def Title}
    \zhlipsum[2]
\end{mytcbbox}

\begin{mytcbbox}[skyblue]{My Def Title}
    \zhlipsum[name=zhufu]
\end{mytcbbox}

\end{document}

image.png

Note:

  1. 懂得使用md代码块,这非常好(!)
  2. 题目还可以改进,需要体现这个样式的特征,例如『实现boxrule断开样式』而不是泛泛的『实现某种特定的边框』,好的题目可以让本post更容易被需要的人搜到

3.

上边框仅绘制两端长度为 3 em (可调整)的部分

因为一些原因,我不想暴露出控制这个长度的接口,如果确有需要修改,你可以自行试试修改以下绘制横线的长度(-2.9em3em):

overlay={%
    \draw[color=#1,line width=2pt,line cap=round]
    ([yshift=-1pt]frame.west)--++(-2.9em,0) 
    ([yshift=-1pt]frame.east)--++(3em,0);
}
4 个回答
远方不远
远方不远 1天前
Hello, LuaLaTeX!

凑个热闹
MWE中凡与此问题无关联的内容都应该酌情删改,否则可能影响潜在答题者的解答质量。
实际上,你的导言区只需要这几句代码:

% !TEX program = pdflatex
\documentclass[openany]{book}
\usepackage[many]{tcolorbox}
\usepackage{hyperref}

应该等你确实需要了,再往导言区加东西。例如,添加你的额外需求实现\Doubleref

% !TEX program = pdflatex
\documentclass[openany]{book}
\usepackage[many]{tcolorbox}
\usepackage{hyperref}
\NewDocumentCommand{\Doubleref}{m}{{\color{red}Definition \ref{#1} (\nameref{#1})}}

总之,做MWE时秉持越少越好原则,才能更方便地排查错误。
然后我也浅答一个,完全用tcolorbox实现的效果:
image.png
image.png
image.png
image.png
而要实现这个效果,只需如下定制即可:

\newtcbtheorem
    [number within=chapter]
    {definition}
    {Definition}
    {
        fonttitle=\bfseries\color{black},
        opacityback=0,
        left=.25em,
        right=.25em,
        top=.45ex,
        bottom=.45ex,
        before skip=2pt plus 2pt minus 1pt,
        after skip =6pt plus 2pt minus 4pt,
        arc=0pt,
        enhanced,
        breakable,
        boxrule=0pt,
        frame hidden,
        borderline south={1pt}{0mm}{black},
        borderline west ={1pt}{0mm}{black},
        borderline east ={1pt}{0mm}{black},
        attach boxed title to top left={
            yshift=-3mm,
            yshifttext=-1mm,
            xshift=3em 
        },
        overlay unbroken and first={
            \draw [line width=1pt] (title.west) -- ++(-3em+.5pt,0pt) -- ++(down:\baselineskip);
            \draw [line width=1pt] (title.east) -- ++( 3em,0pt);
        },
        overlay middle and last={},
        boxed title style={
            frame style   ={fill=none},
            interior style={fill=none},
            left=.25em,
            right=.25em,
            top=.45ex,
            bottom=.45ex
        }
    }
    {def}

其中参数的含义是:

\newtcbtheorem
    [<初始化选项>]            %上面用到了计数器关联,也可以在此处理cleveref兼容问题
    {<新环境的name>}          %用于\begin{}...\end{}的环境名
    {<用于展示的name>}        %用于排版结果中展示的环境名
    {<定制tcb的选项>}         %主要是操纵外观
    {<标签的前缀>}            %人为将标签分为前缀、分隔符(默认使用英文冒号)和主体

然后在正文区使用

\begin{<新环境的name>}{<定理的标题文本>}{<标签的主体>}
    ...
\end{<新环境的name>}

例如

\begin{definition}{GouGu}{gougu}
    ...
\end{definition}

即可创建一个基于定制tcolorbox的新定理。
然后在正文区其他地方使用

\Doubleref{<标签的前缀>:<标签的主体>}

例如

\Doubleref{def:gougu}

即可交叉引用。
如需兼容cleveref宏包,需注意导言区的代码顺序,且需要在\newtcbtheorem的可选参数[<初始化选项>]里增加,Crefname={Definition}{Definitions}。然后即可采用由cleveref宏包提供的交叉引用类型。


原题没有提出断页需求,因此未进行测试,代码已修改。原来使用的frame code app在不断页的条件下的确可以正常工作,但是当分页发生时,主盒子会被保存到一个寄存器中,所以原先的主盒子会消失,这将导致原先的盒子的追加代码失效。在tcb手册中对此问题有专门叙述,解决方案之一是分别定制盒子的前中后部分以及不可断页共四种类型的皮肤。完整代码在此。

Eureka
Eureka 1天前
这家伙很懒,什么也没写!

不知道题主有没有解决这个 cref 的问题,所以我这里来推荐一下我自己写的这个模板,它可以很方便的处理上面的 定理类环境样式 定制与 cref 问题。

  • 在定理环境样式上,我这个模板提供了很多的接口: 标题格式定制,环境颜色控制, ....
  • cref 上,我这个模板内置了 cleverefzref-clever 两种兼容方案(因为最新的 cleveref 在中文环境下出了点问题)

使用我这个模板,对应的解决方案如下:

\documentclass[lang=cn, fancy]{ztex}
\makeatletter
\zthmstylenew{
  styleA={
    begin={
      \begin{tcolorbox}[
        enhanced jigsaw,
        breakable, sharp corners, 
        colframe=\thm@tmp@color, 
        top=2ex, boxrule=2pt, toprule=0pt, 
        fonttitle=\large\bfseries, colback=white, 
        attach boxed title to top left={xshift=3em,yshift=-\tcboxedtitleheight/2},
        coltitle=\thm@tmp@color, title={\zthmname~\zthmnumber},
        boxed title style={%
          empty, left=1pt, right=1pt, bottom=0pt,
          overlay={%
            \draw[color=\thm@tmp@color,line width=2pt,line cap=round]
            ([yshift=-1pt]frame.west)--
            ++(-2.9em,0) ([yshift=-1pt]frame.east)--
            ++(3em,0);
          }
        },
      ]
    },
    end = {\end{tcolorbox}},
  }
}
\makeatother
\zthmstyle{styleA}
\zthmlang{en}
\usepackage{zhlipsum}
\usepackage{lipsum}


\begin{document}
\section{FIRST}
\lipsum[1][1-2]
\begin{definition}[DEF-TEST]\label{def:A}
  \zhlipsum[1]
\end{definition}
\lipsum[1][3-5] -- \cref{thm:A}.


\vspace*{13em}
\section{SECOND}
\begin{theorem}[THM-TEST]\label{thm:A}
  \lipsum[1]
\end{theorem}
\lipsum[1][3-5] -- \cref{def:A}.
\end{document}
对应的样式代码是直接抄的 @u70550 的, 加了一丢丢的改动.

编译结果:
image.png

如果有兴趣使用我这个模板,我可以再发给你,因为目前我这模板还没有发布.
Ethebeth
Ethebeth 9小时前
这家伙很懒,什么也没写!

目前我使用的如下:

  \newtcbtheorem
    [number within=chapter, Crefname={Definition}{Definitions}]
    {definition}
    {Definition}
    {
        fonttitle={\bfseries\fontsize{14}{14}\selectfont\color{colorDefinition}},
        opacityback=0,
        left=.75em,
        right=.75em,
        top=1.5ex,
        bottom=1.2ex,
        before skip=10pt plus 1pt minus 1pt,
        after skip =14pt plus 1pt minus 1pt,
        arc=0pt,
        enhanced,
        breakable,
        boxrule=0pt,
        frame hidden,
        borderline south={1pt}{0mm}{colorDefinition},
        borderline west ={1pt}{0mm}{colorDefinition},
        borderline east ={1pt}{0mm}{colorDefinition},
        attach boxed title to top left={
            yshift=-8pt,
            yshifttext=-1mm,
            xshift=2em 
        },
        overlay ={
          \begin{tcbclipinterior}
            \draw [line width=1pt, color=colorDefinition]
              ([yshift=-2.5pt]title.west) -- ++(-2em,0pt);
            \draw [line width=1pt, color=colorDefinition]
              ([yshift=-2.5pt]title.east) -- +(2em,0pt);
          \end{tcbclipinterior}
        },
        boxed title style={
            frame style   ={fill=none},
            interior style={fill=none},
            left=.25em,
            right=.25em,
            top=.25ex,
            bottom=.25ex,
            height=20pt
        }
    }
    {def}

改动之处包括增加 boxed title style 的 height 属性,保证添加了标题(比如 Definition 添加标题 poutine)之后不会影响 box 的位置(从而影响画的横线)。
使用 overlay 而非 frame code app,这样在跨页时仍然能正确绘制。

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览