[Tex/LaTex] Horizontal lines touching the multicol column separator rule

multicolpositioningrules

Is there a possibility to put a horizontal line above and below a multicolumn output (using the multicol package) such that the horizontal lines touch the multicol column separator exactly at its borders?

Graphically depicted, it should look as follows:

----------------
       |
       |
       |
----------------

Best Answer

Here is one option via the new environment multicolumns. It takes a single argument, similar in nature to that of the multicol environment:

\begin{multicolumns}{<colnum>}
%...
\end{multicolumns}

enter image description here

\documentclass{article}
\usepackage{multicol}% http://ctan.org/pkg/multicol
\usepackage{xcolor}% http://ctan.org/pkg/xcolor
\usepackage{lipsum}% http://ctan.org/pkg/lipsum
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox

\makeatletter
\patchcmd{\endmulticols}{\par}{\par\xdef\@@tpd{\the\prevdepth}}{}{}
\newenvironment{multicolumns}[1]
  {% \begin{multicolumns}{<cols>}
   \par\nobreak % don't break a page here
   \kern\dimexpr\the\prevdepth+\multicolsep\relax % don't take into account the depth of the preceding line + #2
   {\columnseprulecolor\hrule height \columnseprule} % the rule, same width as \columnseprule
   \kern-\multicolsep % space after the rule
   \nointerlineskip % no additional space after the rule
   \begin{multicols}{#1}
  }
  {% \end{multicolumns}
   \end{multicols}%
   \par\nobreak % don't break a page here
   \kern\dimexpr\@@tpd-\multicolsep\relax % don't take into account the depth of the preceding line + #2
   {\columnseprulecolor\hrule height \columnseprule} % the rule, same width as \columnseprule
   \kern\multicolsep % space after the rule
   \nointerlineskip % no additional space after the rule
  }
\makeatother

\setlength{\columnseprule}{.4pt}% Column separator rule width
\begin{document}
\lipsum[1]
\begin{multicolumns}{2}
\lipsum[2-3]
\end{multicolumns}
\lipsum[4]
\end{document}

At \begin{multicolumns}, a vertical correction is made in terms of the skip (\multicolsep), added by the multicol package. This is also corrected at \end{multicolumns}. However, capturing \prevdepth is also required, leading to the use of etoolbox to patch \endmulticol.

The \hrule has been made to match \columnseprule. This can be changed, if needed. To see the effect, use something like \setlength{\columnseprule}{1pt}. Additionally, since xcolor is loaded, you can modify the colour of the column separation rule \columnseprulecolor, which will translate to the top/bottom horizontal rules. For example, use \renewcommand{\columnseprulecolor}{\color{orange}} to see the effect.

One caveat: The use of \prevdepth relies on the last line within the multicolumn environment. As such, if the last line (in the right-most column) has no descenders (like j, p, q, g or y), then the alignment will be off. Consider, for example:

% same preamble as above
\begin{document}
\lipsum[1]
\begin{multicolumns}{2}
\lipsum*[2-3] Here is some more filler text to fill the line.
\end{multicolumns}
\lipsum[4]
\end{document}

enter image description here

This should be manually corrected with either some \vphantom{<descender>} (say), or an ending \strut. Or, alternatively, could be included in the patch of \endmulticol for more general usage. The latter is preferred since it also leaves a better vertical gap between the descenders and the \hrule. For example, consider

% same preamble above
\patchcmd{\endmulticols}{\par}{\strut\par\xdef\@@tpd{\the\prevdepth}}{}{}
% same preamble below and entire document

enter image description here