5

I would like to design a simple environment which displays examples. This is what I got so far:

\documentclass{article}
\usepackage{xcolor}
\usepackage{parskip}
\usepackage{lipsum}

\makeatletter
  \newcommand\filltoend{\leavevmode\leaders\hrule height 0.7ex depth \dimexpr0.4pt-0.7ex\hfill\kern0pt}
  \newcounter{example}
  \newenvironment{example}[1][]{%
    \refstepcounter{example}%
    \textbf{Example~\theexample{}}~{\color{gray}\filltoend}% number and line
    \nopagebreak% is this the right place?
    \par% should I call other vertical spacing commands so I can use the plus/minus syntax?
    \textbf{#1}% Heading
    \par\itshape\ignorespaces%
  }{%
     \\% it would be nice to keep this together with contents
     {\color{gray}\null\filltoend\null}
  }

\makeatother


\begin{document}
\lipsum[1-4]
\begin{example}[My example]
    \lipsum[5]
\end{example}
\end{document}

This is simple and kind of ok.

How can I specify that I want some non-strechable vertical space between the example's number and line, heading and text? How do I discourage LaTeX from putting page breaks between the header components?

In other words: I would like to keep the Example # ---, heading, and start of inner paragraph together, on the same page and without too large spacing between them.

1
  • You can put any vertical space right after \par in your code. I would also put that \nopagebreak after \par and before the vertical space, but it is probably OK where it is.
    – Dan
    Commented Feb 11, 2014 at 20:18

3 Answers 3

5

If you are willing to use an additional package, I'd suggest you to use tcolorbox. This offers you endless customization possibilities and offers you mechanisms to solve the issues you mention (no page breaks in the title, minimum 5 lines before a page break, automatic handling of the optional argument, easily customization of spacing betwee the various elements).

Here's a little example emulating your environment:

\documentclass{article}
\usepackage[a5paper]{geometry}% just for the example
\usepackage{lipsum}
\usepackage{tcolorbox}
\tcbuselibrary{most}

\tcbset{mybox/.style={
  before={\par\vskip3ex\noindent},
  after={\par\vskip1.5ex}}}

\newtcolorbox[auto counter=example]{example}[1][]{
breakable,
mybox,
notitle after break,
lines before break=5,
enhanced,
colback=white,
colframe=white,
coltitle=black,
fonttitle=\bfseries,
arc=0pt,
outer arc=0pt,
leftrule=0pt,
rightrule=0pt,
left=0pt,
right=0pt,
boxsep=0pt,
toptitle=.5\baselineskip,
bottomtitle=-.1\baselineskip,
title=#1,
enlarge top by=4ex,
overlay unbroken={
    \node[fill=white,anchor=west,font=\bfseries,inner xsep=0pt] 
      at (frame.north west) (title) {Example~\thetcbcounter\enspace};
    \draw[thick] (title.east|-frame.north east) -- (frame.north east);
    \draw[thick] (frame.south west) -- (frame.south east);
  },
overlay first={
    \node[fill=white,anchor=west,font=\bfseries,inner xsep=0pt] 
      at (frame.north west) (title) {Example~\thetcbcounter\enspace};
    \draw[thick] (title.east|-frame.north east) -- (frame.north east);
  },
overlay last={
    \draw[thick] (frame.south west) -- (frame.south east);
  },
}


\begin{document}
\lipsum[5]
\begin{example}[My example]
\lipsum[5]
\end{example}
\lipsum[5]
\begin{example}
\lipsum[1-3]
\end{example}
\lipsum[5]

\end{document}

enter image description here

1
  • This package seems powerful indeed but looked like an overkill for my simple purposes. Plus, I really wanted to learn how it should be done.
    – Bordaigorl
    Commented Feb 12, 2014 at 19:42
0

The heading is now actually part of the first line of text, so it cannot be separated.

\documentclass{article}
\usepackage{xcolor}
\usepackage{parskip}

\newlength{\test}

\newcommand\filltoend{\leavevmode\leaders\hrule height 0.7ex depth \dimexpr0.4pt-0.7ex\hfill\kern0pt}
  \newcounter{example}
  \newenvironment{example}[1][]{%
  \refstepcounter{example}%
  \vspace{0.5\baselineskip}\par\noindent%
  \raisebox{\baselineskip}{\parbox[b]{\linewidth}%
  {\textbf{Example~\theexample{}}~{\color{gray}\filltoend}% number and line
  \settowidth{\test}{#1}\ifdim\test>0pt% test for optional argument
  \vspace{0.5\baselineskip}\linebreak\textbf{#1}\fi}% Heading
  \hspace{-\linewidth}}\hspace{\parindent}%start of text
    }{%
  \hfill% the following acts as a strut at the end of the line
  {\hspace{-\linewidth}\color{gray}\rule[-.5\baselineskip]{\linewidth}{.4pt}}
  \par
}

\begin{document}
\rule{1pt}{.88\textheight}\\% Easier to adjust
last line.

\begin{example}[My example]% adds a space if not commented
Fusce mauris. Vestibulum luctus nibh at lectus. Sed bibendum, nulla a faucibus
semper, leo velit ultricies tellus, ac venenatis arcu wisi vel nisl. Vestibulum diam.
Aliquam pellentesque, augue quis sagittis posuere, turpis lacus congue quam,
in hendrerit risus eros eget felis. Maecenas eget erat in sapien mattis porttitor.
Vestibulum porttitor. Nulla facilisi. Sed a turpis eu lacus commodo facilisis.
Morbi fringilla, wisi in dignissim interdum, justo lectus sagittis dui, et vehicula
libero dui cursus dui. Mauris tempor ligula sed lacus. Duis cursus enim ut
augue. Cras ac magna. Cras nulla. Nulla egestas. Curabitur a leo. Quisque
egestas wisi eget nunc. Nam feugiat lacus vel est. Curabitur consectetuer.
\end{example}

New paragraph.
\end{document}

To get the end of the environment to work I had to use actual text instead of \lipsum, which must include a \par at the end of each paragraph.

8
  • This is not what I need since I want to allow pagebreaks in between paragraphs of the content section, but avoiding too much spacing or page breaks between the heading and the contents. I found a solution, I'll post it tomorrow
    – Bordaigorl
    Commented Feb 11, 2014 at 23:40
  • Okay, I changed to a completely different approach. Commented Feb 12, 2014 at 2:24
  • Isn't this fiddling with negative spaces really fragile? Wouldn't it be better to use skips with custom stretchability, \addtovspace and \unskip or similar commands?
    – Bordaigorl
    Commented Feb 12, 2014 at 20:01
  • For removing the bottom margin from \lipsum, sure. But then no one is going to use \lipsum for anything but a test (and hopefully not even then). This is the first time I tried the \rule\vspace combo and it tested well. It sure works better than \pagebreak[3]! Commented Feb 12, 2014 at 22:26
  • 1
    Penalties are how TeX works internally, so are probably more robust, if obscure. My approach was based on struts. Commented Mar 3, 2014 at 15:14
0

I came up with my own solution and I am sharing it here since it might be useful to others.

Using tcolorbox, mdframed and similar packages is an option but first, I wanted to know how to do proper spacing, second the lines will not necessarily be in my final design, third they seemed an overkill (they use tikz) for what I needed.

So, I had a look at this question Environment with first paragraph in bold and no pagebreaks and realised that the way to go is setting penalties and widow/orphan values. So, in order to have a paragraph break that discourages page breaks and keeps the text together you can define something like:

\newcommand{\nbpar}{\widowpenalty=10000 \@@par\penalty10000}

then my environment can be rewritten as

\newenvironment{example}[1][]{%
  \def\@extitle@{#1}%
  \refstepcounter{example}%
  \par\smallskip%
  {\parskip=0.5\baselineskip \advance\parskip by 0pt plus 0pt%
  \textbf{Example~\theexample{}}~{\color{gray}\filltoend}%
  \ifx\@extitle@\@empty\relax\else\nbpar\textbf{#1}\fi\nbpar\mbox{}}%
  \itshape\ignorespaces}%
  {\nbpar{\color{gray}\filltoend\mbox{}}}

there I also redefined (in a group) \parskip so I can control how stretchable the space in the heading block is.

Now, since I did not really like how it looked, I settled for a simpler but yet, I think, nice way of setting apart the example from the rest of the content: bold heading, and an ornament at the end; using \nbpar as above to handle spacing.

\usepackage{adforn}
\newcommand{\exOrnament}{\adforn{21}}

\newenvironment{example}[1][]{%
  \def\@extitle@{#1}%
  \refstepcounter{example}%
  \par\medskip%
  {\parskip=0.5\baselineskip \advance\parskip by 0pt plus 0pt
  \textbf{Example~\theexample{}}%
  \ifx\@extitle@\@empty\relax\else~--~\textbf{#1}\fi\nbpar\makebox{}}%
  \itshape\ignorespaces}%
  {\unskip\nbpar\hfill\exOrnament\hfill\mbox{}\par}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .