30 如何实现章节标题后根据是否直接接正文自动插入额外垂直间距? 4天23时14分58秒

发布于 2025-07-20 16:44:41

在使用 ctexbook 文档类编写中文文档时,我希望实现如下逻辑:当某级标题(如 chapter、section、subsection)后紧跟的是下一级标题,则正常渲染,不插入额外间距;但若标题后直接接正文内容(普通段落),则在标题和正文之间自动插入一段自定义的垂直距离(如vspace{2em})。这个需求不能通过简单设置 afterskip 解决,因为它会作用于所有情况,无法区分是否有子标题。请问如何优雅地实现该自动判断逻辑,并与 CTEXsetup 设定的章节样式兼容?

附上最小可复现示例代码:

\documentclass[UTF8,oneside,a4paper,12pt]{ctexbook}
\usepackage{ctex}
\CTEXsetup[
    name={},
    break = ,
    number={\arabic{chapter}}, % 章节编号设置为阿拉伯数字格式
    format+={\zihao{-2}\heiti},
    aftername={\,\,\,},
    beforeskip={-1.5em},
    afterskip={1.3em}
]{chapter}

\CTEXsetup[
    format={\zihao{4}\heiti},
    nameformat+={\zihao{4}\heiti},
    aftername={\,\,\,},
    titleformat={\zihao{4}\heiti},
    beforeskip={0.3em},
    afterskip={0.1em}
]{section}

\CTEXsetup[
    format={\zihao{-4}\heiti},
    nameformat+={\zihao{-4}\heiti},
    aftername={\,\,\,},
    titleformat={\zihao{-4}\heiti},
    beforeskip={0em},
    afterskip={0.62em}
]{subsection}

\CTEXsetup[
    format={\zihao{-4}\heiti},
    nameformat+={\zihao{-4}\heiti},
    aftername={\,\,\,},
    titleformat={\zihao{-4}\heiti},
    beforeskip={0ex},
    afterskip={0ex}
]{subsubsection}

\setcounter{secnumdepth}{3}

\begin{document}

\chapter{这是章标题这是章标题这是章标题}
\section{SECTION-SECTION-SECTION-SECTION}
\subsection{SUBSECTION-SUBSECTION-SUBSECTION-SUBSECTION}
\subsubsection{SUBSUBSECTION-SUBSUBSECTION-SUBSECTION-SUBSECTION}

\vspace{3em}

\chapter{这是章标题这是章标题这是章标题}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\section{SECTION-SECTION-SECTION-SECTION}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\subsection{SUBSECTION-SUBSECTION-SUBSECTION-SUBSECTION}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\subsubsection{SUBSUBSECTION-SUBSUBSECTION-SUBSECTION-SUBSECTION}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\end{document}

查看更多

关注者
0
被浏览
244
3 个回答
Izumi Sakai
Izumi Sakai 20小时前
Ph.D. in Physics at Westlake University

Hope this may help u: using l3bool

image.png

\documentclass[AutoFakeBold, oneside,a4paper,12pt]{ctexbook}

\makeatletter
\ExplSyntaxOn
\bool_new:N \l_@@_chapter_afterskip_bool
\hook_gput_code:nnn { cmd / chapter / before } {.}
  { \bool_gset_true:N \l_@@_chapter_afterskip_bool }
\hook_gput_code:nnn { cmd / @startsection / before } {.}
  { \bool_if:NT \l_@@_chapter_afterskip_bool { \vskip -2em } }
% 使用 vskip: 否则 chapter 后紧挨着的正文结尾、和接下来第一个 section 标题
% 之间距离会变小甚至重叠
\DeclareDocumentCommand \banchapterskip {}
  { \bool_gset_false:N \l_@@_chapter_afterskip_bool }
\ExplSyntaxOff
\makeatother

\ctexset{
  secnumdepth = 3,
  chapter = {
    name        = {}, break       = ,
    number      = \arabic{chapter},
    format+     = \zihao{-2}\heiti,
    aftername   = \,\,\,,
    beforeskip  = -1.5em,
    afterskip   = 3.3em
  },
  section = {
    format      = \zihao{4}\heiti,
    nameformat+ = \zihao{4}\heiti,
    aftername   = \,\,\,,
    titleformat = \zihao{4}\heiti,
    beforeskip  = 0.3em,
    afterskip   = 0.1em,
    aftertitle+ = \banchapterskip
  },
  subsection = {
    format      = \zihao{-4}\heiti,
    nameformat+ = \zihao{-4}\heiti,
    aftername   = \,\,\,,
    titleformat = \zihao{-4}\heiti,
    beforeskip  = 0em,
    afterskip   = 0.62em
  },
  subsubsection = {
    format      = \zihao{-4}\heiti,
    nameformat+ = \zihao{-4}\heiti,
    aftername   = \,\,\,,
    titleformat = \zihao{-4}\heiti,
    beforeskip  = 0ex,
    afterskip   = 0ex
  }
}

\begin{document}

\chapter{这是章标题这是章标题这是章标题}
\section{SECTION-SECTION-SECTION-SECTION}
\subsection{SUBSECTION-SUBSECTION-SUBSECTION-SUBSECTION}
\subsubsection{SUBSUBSECTION-SUBSUBSECTION-SUBSECTION-SUBSECTION}

\vspace{3em}

\chapter{这是章标题这是章标题这是章标题}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\section{SECTION-SECTION-SECTION-SECTION}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\subsection{SUBSECTION-SUBSECTION-SUBSECTION-SUBSECTION}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\subsubsection{SUBSUBSECTION-SUBSUBSECTION-SUBSECTION-SUBSECTION}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\end{document}
飘石
飘石 19小时前
这家伙很懒,什么也没写!

优雅的方法可能是重定义\@startsection,或者可能用\AddToHook也行(我不会)?

只会一个不优雅的方法,重新定义\chapter,\section,...让它们多读一个参数,对这个参数进行判断。
存在的问题:

  1. 这些命令后面不能有空行。所以在原最小可复现示例代码中,正文部分的\vspace{3em}前面的空行我删除了。
  2. 如果要交叉引用,还要判断比如\label{section-1}后面的内容,这段代码处理不了。
  3. 其它我想不到但一定存在的问题...
\documentclass[UTF8,oneside,a4paper,12pt]{ctexbook}
\usepackage{ctex}
\CTEXsetup[
    name={},
    break = ,
    number={\arabic{chapter}}, % 章节编号设置为阿拉伯数字格式
    format+={\zihao{-2}\heiti},
    aftername={\,\,\,},
    beforeskip={-1.5em},
    afterskip={1.3em}
]{chapter}

\CTEXsetup[
    format={\zihao{4}\heiti},
    nameformat+={\zihao{4}\heiti},
    aftername={\,\,\,},
    titleformat={\zihao{4}\heiti},
    beforeskip={0.3em},
    afterskip={0.1em}
]{section}

\CTEXsetup[
    format={\zihao{-4}\heiti},
    nameformat+={\zihao{-4}\heiti},
    aftername={\,\,\,},
    titleformat={\zihao{-4}\heiti},
    beforeskip={0em},
    afterskip={0.62em}
]{subsection}

\CTEXsetup[
    format={\zihao{-4}\heiti},
    nameformat+={\zihao{-4}\heiti},
    aftername={\,\,\,},
    titleformat={\zihao{-4}\heiti},
    beforeskip={0ex},
    afterskip={0ex}
]{subsubsection}

\setcounter{secnumdepth}{3}

\ExplSyntaxOn
\cs_new:Npn \__My_judgement:nn #1#2
{
  \tl_if_in:nnTF {#1}{#2}
  {\par #2}
  {\vspace{3em minus 3em}\par #2}
}

\cs_set_eq:NN \__My_oldchapter        \chapter
\cs_set_eq:NN \__My_oldsection        \section
\cs_set_eq:NN \__My_oldsubsection     \subsection
\cs_set_eq:NN \__My_oldsubsubsection  \subsubsection
\RenewDocumentCommand{\chapter}{somm}
{
  \IfBooleanTF{#1}
  { \IfNoValueTF {#2} { \__My_oldchapter*{#3} } { \__My_oldchapter*[#2]{#3} } }
  { \IfNoValueTF {#2} { \__My_oldchapter{#3}  } { \__My_oldchapter[#2]{#3}  } }
  \__My_judgement:nn {\chapter,\section,\subsection,\subsubsection}{#4}
}
\RenewDocumentCommand{\section}{somm}
{
  \IfBooleanTF{#1}
  { \IfNoValueTF {#2} { \__My_oldsection*{#3} } { \__My_oldsection*[#2]{#3} } }
  { \IfNoValueTF {#2} { \__My_oldsection{#3}  } { \__My_oldsection[#2]{#3}  } }
  \__My_judgement:nn {\chapter,\section,\subsection,\subsubsection}{#4}
}
\RenewDocumentCommand{\subsection}{somm}
{
  \IfBooleanTF{#1}
  { \IfNoValueTF {#2} { \__My_oldsubsection*{#3} } { \__My_oldsubsection*[#2]{#3} } }
  { \IfNoValueTF {#2} { \__My_oldsubsection{#3}  } { \__My_oldsubsection[#2]{#3}  } }
  \__My_judgement:nn {\chapter,\section,\subsection,\subsubsection}{#4}
}
\RenewDocumentCommand{\subsubsection}{somm}
{
  \IfBooleanTF{#1}
  { \IfNoValueTF {#2} { \__My_oldsubsubsection*{#3} } { \__My_oldsubsubsection*[#2]{#3} } }
  { \IfNoValueTF {#2} { \__My_oldsubsubsection{#3}  } { \__My_oldsubsubsection[#2]{#3}  } }
  \__My_judgement:nn {\chapter,\section,\subsection,\subsubsection}{#4}
}

\ExplSyntaxOff

\begin{document}

\chapter{这是章标题这是章标题这是章标题}
\section{SECTION-SECTION-SECTION-SECTION}
\subsection{SUBSECTION-SUBSECTION-SUBSECTION-SUBSECTION}
\subsubsection{SUBSUBSECTION-SUBSUBSECTION-SUBSECTION-SUBSECTION}
\vspace{3em}

\chapter{这是章标题这是章标题这是章标题}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\section{SECTION-SECTION-SECTION-SECTION}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\subsection{SUBSECTION-SUBSECTION-SUBSECTION-SUBSECTION}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\subsubsection{SUBSUBSECTION-SUBSUBSECTION-SUBSECTION-SUBSECTION}
正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文正文
\end{document}                                                            
Izumi Sakai
Izumi Sakai 19小时前
Ph.D. in Physics at Westlake University

hook 很容易的,无论你使用 2e 提供的也好还是 3 提供的也好:

\hook_gput_code:nnn {<hook>} {<label>} {<commands>}

没必要重新定义几个标题命令.

撰写答案 当前问题悬赏金额为¥30 元,被提问者采纳后将获得赏金

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

发布
问题

分享
好友

手机
浏览

扫码手机浏览