1

Added 2020-07-05 -- Details of my requirements:

Produce a document that frames doublecol and onecol:

The frame is supposed to

  1. completely frame all content of the document
  2. within one frame
  3. that is open between (and only between) pagebreaks.

As for the content within the frame

  1. The CONTENT has alternating doublecol
  2. AND onecol

Pagenumbers: I could live with pagenumbers not being framed, but that would be nice.

So the code would ideally look like as follows:


\usepackage{mdframed}                   % Alternative1
%\usepackage{framed}                    % Alternative2
\usepackage{multicol}
\usepackage{lipsum}

\begin{document}
    \begin{mdframed}                % Alternative1
    %\begin{framed}                 % Alternative2
    
        \begin{multicols}{2}
        \lipsum[1-10]       
        \end{multicols}

        \lipsum[1-2]
        
        \begin{multicols}{2}
        \lipsum[1-10]       
        \end{multicols}

    \end{mdframed}                  % Alternative1
    %\end{framed}                   % Alternatice2

\end{document}

Is not working: mdframed, framed

BUT: when the text spans more than one page e.g. using \lipsum[1-10], the compiler get's lost within a stack-overflow saying

"! TeX capacity exceeded, sorry [input stack size=5000].@xiipt ->12 \end{framed}."

I learned from the documentation page 6 3.1 Preface to version 1.4 that

The only restriction to such inner multicols environments (nested, or within TEX's internal vertical mode) is that such variants will produce a box with the balanced material in it, so that they can not be broken across pages or columns.

So it seems that LaTex is trying to a) open a frame b) render the two columns c) can't deliver pages because two columns haven't been distributed over the document and then d) dies because it woud not know how to close the frame for the first page.

Is not working: twocolumn as a doc-class parameter

\documentclass[twocolumn]{article}
...

but this will produce a frame around each column - which I don't want.

**Is not working:

It can't be that difficult - seems to be such a simple common problem. How to achieve that?

Thanks for your efforts.

Crosspost Links ---------------------- TexWelt.de golatex.de


1

Update #2 One way to size the frame to the final text is to save the y-position at the end of the document, and then use that to calculate the `\layerheight' on the final page.

This solution uses zref to find that position. You'll need two runs.

\documentclass{article}
\usepackage{scrlayer}
\usepackage{multicol}
\usepackage[savepos]{zref}
\usepackage{lipsum}

\newlength{\marginpadding}
\setlength{\marginpadding}{4pt}

\DeclareNewLayer[textarea,background,mode=picture,
  addheight=2\marginpadding,
  addwidth=2\marginpadding,
  addhoffset=-\marginpadding,
  addvoffset=-\marginpadding,
  contents={%
  \putLR{\line(0,1){\LenToUnit{\layerheight}}}%
  \putUR{\line(-1,0){\LenToUnit{\layerwidth}}}%
  \putUL{\line(0,-1){\LenToUnit{\layerheight}}}%
}]{topbox}
\DeclareNewLayer[clone=topbox,
  contents={%
  \putLR{\line(0,1){\LenToUnit{\layerheight}}}%
  \putUL{\line(0,-1){\LenToUnit{\layerheight}}}%
}]{midbox}
\DeclareNewLayer[clone=topbox,
  height={\pdfpageheight-\zposy{textbottom}sp-\layeryoffset-\baselineskip+\marginpadding},
  contents={%
  \putLL{\line(1,0){\LenToUnit{\layerwidth}}}%
  \putLR{\line(0,1){\LenToUnit{\layerheight}}}%
  \putUL{\line(0,-1){\LenToUnit{\layerheight}}}%
}]{bottombox}
\DeclarePageStyleByLayers{firstpage}{topbox}
\DeclarePageStyleByLayers{midpage}{midbox}
\DeclarePageStyleByLayers{lastpage}{bottombox}
\pagestyle{midpage}
\begin{document}
\thispagestyle{firstpage}
\begin{multicols}{2}
  \lipsum[1-10]       
\end{multicols}

\lipsum[1-2]

\begin{multicols}{2}
  \lipsum[1-10]
\end{multicols}
\zsaveposy{textbottom}
\thispagestyle{lastpage}
\end{document}

frame on final page

Updated Answer (2020/07/06)

I'm still not completely clear on your requirements, but if what you're really asking for is a frame whose size is fixed and simply adapts its shape depending on what page you are on, you can do this with the page styles provided by the scrlayer package.

The following works as long as you know you have more than one page of content. (You could add some logic to test for a one-page doc if you really needed it.) The basic idea is to create three page styles, make the middle page style the default, and set the top and bottom styles for a single page at the beginning and end.

The frame is very simple (it's adapted from the KOMA-Script manual--see chapter 17), but you could replace the contents with a much more sophisticated image if you desire.

\documentclass{article}
\usepackage{scrlayer}
\usepackage{multicol}
\usepackage{lipsum}

\newlength{\marginpadding}
\setlength{\marginpadding}{4pt}

\DeclareNewLayer[textarea,background,mode=picture,
  addheight=2\marginpadding,addwidth=2\marginpadding,
  addhoffset=-\marginpadding,addvoffset=-\marginpadding,
  contents={%
  \putLR{\line(0,1){\LenToUnit{\layerheight}}}%
  \putUR{\line(-1,0){\LenToUnit{\layerwidth}}}%
  \putUL{\line(0,-1){\LenToUnit{\layerheight}}}%
}]{topbox}
\DeclareNewLayer[textarea,background,mode=picture,
  addheight=2\marginpadding,addwidth=2\marginpadding,
  addhoffset=-\marginpadding,addvoffset=-\marginpadding,
  contents={%
  \putLR{\line(0,1){\LenToUnit{\layerheight}}}%
  \putUL{\line(0,-1){\LenToUnit{\layerheight}}}%
}]{midbox}
\DeclareNewLayer[textarea,background,mode=picture,
  addheight=2\marginpadding,
  addwidth=2\marginpadding,
  addhoffset=-\marginpadding,
  addvoffset=-\marginpadding,
  contents={%
  \putLL{\line(1,0){\LenToUnit{\layerwidth}}}%
  \putLR{\line(0,1){\LenToUnit{\layerheight}}}%
  \putUL{\line(0,-1){\LenToUnit{\layerheight}}}%
}]{bottombox}
\DeclarePageStyleByLayers{firstpage}{topbox}
\DeclarePageStyleByLayers{midpage}{midbox}
\DeclarePageStyleByLayers{lastpage}{bottombox}
\pagestyle{midpage}
\begin{document}
\thispagestyle{firstpage}
\begin{multicols}{2}
  \lipsum[1-10]       
\end{multicols}

\lipsum[1-2]

\begin{multicols}{2}
  \lipsum[1-10]       
\end{multicols}
\thispagestyle{lastpage}
\end{document}

Original Answer

Welcome to Tex.SE.

You could try the package multicolrule. The idea is to create a "column separator" for multicols that actually draws a box around the outside of the columns instead of between them.

\documentclass{article}
\usepackage[tikz]{multicolrule}
\usetikzlibrary{calc}
\usepackage{lipsum}

\SetMCRule{color=gray,width=0.4pt, expand=2pt, custom-line={
  \coordinate (TOPLEFT) at ($(TOP)-(\columnwidth+.5\columnsep,\columnseprule)$);
  \coordinate (TOPRIGHT) at ($(TOP)+(\columnwidth+.5\columnsep,-\columnseprule)$);
  \coordinate (BOTLEFT) at ($(BOT)-(\columnwidth+.5\columnsep,-\columnseprule)$);
  \coordinate (BOTRIGHT) at ($(BOT)+(\columnwidth+.5\columnsep,\columnseprule)$);
  \draw[line width=\columnseprule] (TOPLEFT) -- (TOPRIGHT) -- (BOTRIGHT) -- (BOTLEFT) -- cycle;}}

\begin{document}
\begin{multicols}{2}
  \lipsum
\end{multicols}
\end{document}

This version puts the lines exactly around the edge of the boxes, but you could add a gap if you wanted.

| improve this answer | |
  • Hi Karl, thank you for your reply, your solution works as designed and solves the problem as described. Actually I've been splitting my problems into different parts, to which the above was one of them, but the others remain unresolved, as not mentioned within the problem description: Besides the twocolumn layout I need to switch between twocolum and onecolumn**. Then the above produces a problematic result. So I will complete my problem description! Sorry for that. – Simon Jul 5 at 19:32
  • And Karl, under the added requirements I have not yet fully explored your suggestions. I will hang on there and feed back... Tx – Simon Jul 5 at 21:16
  • More and more I come to the conclusion it's a bad idea to orient on the box that's inside the page being layouted, because I have many of them. I think it's better to work with something that's content indipendent an works with overlaying what's been rendered. Still the problem will remain to start and end the box with a horizontal line ond the first page and the last page, respectively (but not on every page). – Simon Jul 5 at 22:01
  • See my updated answer – Karl Hagen Jul 6 at 14:04
  • Wow - that's so cool! This not only is such a complete answer that it only needs copying, additionally this is a very clean solution! Great, thank you! One thing is left: I would want the closure of the border be at the end of the text - rather that at the end of the page(height=\textlength); but I can't get hold of the variable that holds the height of the textblock that's been shipped out. Can you help here? – Simon Jul 6 at 17:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.