[Tex/LaTex] Defining a new type of floating environment

environmentsfloats

In a document, I need to provide some details about specific topics without disrupting the flow of the main document, so that the details may easily be omitted at first reading. To do so, I thought it would be convenient to write the corresponding paragraphs in a frame outside the body of the document. This can be done easily using, for instance, mdframed, and I can wrap the commands defining the frame into a \newenvironment.

However, I feel that the general layout of the document would be much nicer if the frames were allowed to float and could be numbered and referred to in the main body of the document exactly like figures are. Is there a simple way to create such a floating environment?

So far, the solution I have found is to hijack the figure environment using a new counter, and to redefine the command \theHfigure locally so that hyperlinks built by hyperref point to the right location.

Here is an example:

\documentclass{article}
\usepackage{lipsum}
\usepackage[colorlinks=true]{hyperref}
\usepackage[framemethod=TikZ]{mdframed}
\usepackage{multicol}

\newcounter{framecnt}
\newenvironment{frameenv}[1]
    {\begin{figure}[tb]
    \refstepcounter{framecnt}
    \renewcommand{\theHfigure}{cont.\arabic{framecnt}}
    \begin{mdframed}[roundcorner=10pt,backgroundcolor=blue!10]
    \textbf{\centerline{Frame \arabic{framecnt} --- #1}}
    \smallskip

    \begin{multicols*}{2}
    }
    {\end{multicols*}\end{mdframed}\end{figure}
    }

\begin{document}

\lipsum

\begin{frameenv}{More details}\label{frame1}
\lipsum[1]
\end{frameenv}

See frame \ref{frame1} or figure \ref{fig1}.

\begin{figure}
\caption{A real figure}\label{fig1}
\end{figure}

\end{document} 

and the output it generates:
enter image description here

Does a more "natural" solution exist?

Best Answer

There are a few packages that can help with this- personally I would choose the newfloat package because it is from the same author as the excellent caption package, which means that the two packages work very well together.

Below is a mock up of your original code, but using these two packages; the important lines are

\DeclareFloatingEnvironment[fileext=frm,placement={!ht},name=Frame]{myfloat}
\captionsetup[myfloat]{labelfont=bf}

which sets up a new floating environment- it also creates \jobname.frm which contains information that will be useful if you want to create a list of your frames, using the command

\listofmyfloats

which the newfloat package created for us.

I also moved the hyperref package to be loaded last; this is important, as discussed in Which packages should be loaded after hyperref instead of before?

\documentclass{article}
\usepackage{newfloat}
\usepackage{caption}
\DeclareFloatingEnvironment[fileext=frm,placement={!ht},name=Frame]{myfloat}

\captionsetup[myfloat]{labelfont=bf}
\usepackage{lipsum}
\usepackage[framemethod=TikZ]{mdframed}
\usepackage{multicol}
\usepackage[colorlinks=true]{hyperref}

\newenvironment{frameenv}[1]
    {\begin{myfloat}[tb]
    \begin{mdframed}[roundcorner=10pt,backgroundcolor=blue!10]
    \caption{#1}
    \begin{multicols*}{2}
    }
    {\end{multicols*}\end{mdframed}\end{myfloat}
    }

\begin{document}

\lipsum

\begin{frameenv}{More details}\label{frame1}
\lipsum[1]
\end{frameenv}

See frame \ref{frame1} or figure \ref{fig1}.

\begin{figure}
\caption{A real figure}\label{fig1}
\end{figure}

\end{document} 

Another thought is to make the argument to your environment optional so that you can have an empty caption. This is easily done, using

\newenvironment{frameenv}[1][]
     {\begin{myfloat}[tb]
     ...

which means that you use, noting the square brackets and not braces,

\begin{frameenv}[Details for the caption]\label{frame1}

or

\begin{frameenv}\label{frame2}

You could also remove the caption from the definition of the environment and specify it manually each time, but that's up to you.