6

I would like to set up a tcolorbox where the first paragraph is not indented, but subsequent paragraphs are indented.

I can accomplish this by passing an option like this to the box:

before upper=\setlength{\parindent}{1em}\noindent

The problem with this is that the \noindent causes TeX to enter horizontal mode. So if I start the box with something that should be in vertical mode (e.g., \section), extra vertical is inserted.

Is there a way I can automatically get the output I want without having to create two different kinds of boxes?

MWE

\documentclass{article}

\usepackage{tcolorbox}

\tcbset{mybox/.style={colback=white, colframe=blue, left=2mm, right=2mm,
  fonttitle=\bfseries}, fontupper=\small,
  before upper=\setlength{\parindent}{1em}\noindent}

\newtcolorbox{mybox}[1][]{mybox,#1}

\begin{document}

\begin{mybox}
  The first paragraph should not have an indent.

  Subsequent paragraphs should be indented.
\end{mybox}

\begin{mybox}
  \section{Should not have gap above this heading}
\end{mybox}

\begin{mybox}[before upper=\setlength{\parindent}{1em}]
  \section{Previous box should look like this}
\end{mybox}

\end{document}

MWE output

David Purton
  • 25,884

1 Answers1

6

You can use a simplified version of \@afterheading:

\documentclass{article}

\usepackage{tcolorbox}

\tcbset{mybox/.style={colback=white, colframe=blue, left=2mm, right=2mm,
  fonttitle=\bfseries}, fontupper=\small,
  before upper=\setlength{\parindent}{1em}\everypar{{\setbox0\lastbox}\everypar{}},
}

\newtcolorbox{mybox}[1][]{mybox,#1}

\begin{document}

\begin{mybox}
  The first paragraph should not have an indent.

  Subsequent paragraphs should be indented.
\end{mybox}

\begin{mybox}
  \section{Should not have gap above this heading}
\end{mybox}

\begin{mybox}[before upper=\setlength{\parindent}{1em}]
  \section{Previous box should look like this}
\end{mybox}

\end{document}

enter image description here

The tokens in \everypar are inserted after the paragraph has started, so just after the indentation box; with {\setbox0\lastbox} the indentation box is removed and put in box 0, which is then reset to what it was because the assignment happens in a group. Then \everypar is reset to empty.

egreg
  • 1,121,712
  • That's close! But it has an odd side effect. The vertical space before a center environment disappears. e.g., add \begin{center}Text\end{center} to the end of the first box. – David Purton Aug 07 '19 at 14:56
  • @DavidPurton What would be the reason for keeping that space? – egreg Aug 07 '19 at 15:04
  • A center environment usually has space above and below right? With your code the space is still inserted below the center environment, but removed from above. This seems odd to me :) – David Purton Aug 07 '19 at 15:06
  • @DavidPurton Try \begin{center}Text\end{center} at the top of a minipage. – egreg Aug 07 '19 at 15:07
  • Yeah, but when not at top of a minipage There is still space above. I mean this output is weird (with your \everypar code):\begin{mybox}Text\begin{center}Text\end{center}Text\end{mybox} – David Purton Aug 07 '19 at 15:12
  • Without the \everypar{…} it behaves as I would expect. – David Purton Aug 07 '19 at 15:13
  • Compare also \begin{mybox}Text\begin{itemize}\item Text\end{itemize}Text\begin{center}Text\end{center}Text\end{mybox} Where the itemize spacing is wrong, but the center spacing is right. – David Purton Aug 07 '19 at 15:20
  • @DavidPurton I'm not sure what you mean. If I set top=0pt in the definition of mybox, I get the same space with center, itemize or simple text; more precisely, the first baseline is at the same position in all cases. – egreg Aug 07 '19 at 16:11
  • Sorry, I must not be clear! I have asked a followup question at https://tex.stackexchange.com/questions/503357/followup-controlling-indent-and-vertical-space-at-top-of-a-tcolorbox – David Purton Aug 08 '19 at 10:48