6

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:

----------------
       |
       |
       |
----------------
1

2 Answers 2

6

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

4
  • Nice work!! The default height and width of \hrule are 0.4pt and \hsize, respectively, so it's not strictly necessary to provide the default values of two parameters in the \hrule commands. :-)
    – Mico
    Dec 9, 2011 at 17:21
  • You're right - I actually had higher aspirations for \hrule to perhaps include width and colour modifications, but removed it for "simplicity". I've removed the redundant width and height. Thanks.
    – Werner
    Dec 9, 2011 at 17:23
  • Fantastic! Thank you so much! Were this to be packaged, then I would recommend using the same color as for the column separator, i.e. \columnseprulecolor
    – Yannick
    Dec 9, 2011 at 18:03
  • @Yannick: Nice suggestion. I've added that to my MWE, with the addition of the xcolor package.
    – Werner
    Dec 9, 2011 at 18:31
1

My short answer is "yes, but be careful with what you get." The longer answer is: The multicol package features a length parameter named \multicolsep (default value: 12pt plus 4pt minus 3pt) which governs the amount of vertical space inserted at the beginning and end of a multicols environment. The code that is executed by the package to insert this vertical space is \addvspace\multicolsep. One might think that executing \setlength\multicolsep{0pt} would be the answer your question, but that wouldn't be fully correct. Specifically, while the upper horizontal rule and the inter-column vertical rule will just touch, as is desired, the same is not true for the lower horizontal rule. FMi (the author of the multicol package) seems not to have considered the possibility that anyone would want to set \mulicolsep to 0pt because there's a (minor!) glitch, as the following MWE reveals:

\documentclass{article}
\usepackage{multicol,lipsum}
\setlength{\columnseprule}{0.4pt} % 0.4pt-wide vertical rule between columns 
\setlength{\multicolsep}{0pt}
\begin{document}
\hrule % horizontal rule, 0.4pt wide
\begin{multicols}{2}
\lipsum[3]
\end{multicols}
\hrule % horizontal rule, 0.4pt wide
\end{document}

enter image description here

It is difficult to notice the problem in the image above because of the low resolution, but if you run the MWE on your own system and study the output, you'll observe that the lower horizontal rule is "attached" to the lowest baseline and therefore bisects the descenders of the letters g, p, and q (and even the comma) as well as the column separator rule. Probably not what you want... The problem seems to be caused by the way that the package calculates the lower boundary of the multicolumn "box". Specifically, it would appear that the package's code sets this lower boundary equal to the bottom-most baseline of the box without taking into account that the contents of the bottom-most line of text might contain letters that have descenders that reach below the baseline.

At this point, you may decide to live this glitch (I wouldn't...), dig deep into the package's code to determine how to go about adding a tiny bit of extra vertical space to rectify this problem (I'm not going to do so...), or conclude that setting \multicolsep equal to 0pt and drawing \hrules immediately above and below the multicol environment may just not be a great idea. :-(

Addendum: I just noticed that Werner has posted an answer that fixes the pesky little problem inherent in the way the multicol package computes the lower boundary of the multicols environment. :-)

You must log in to answer this question.

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