5

I'm trying to improve the typesetting of openly licensed books created by my company. We do the typesetting of all our books with LaTeX. The design of these books requires coloured environments that stretch completely across the page as well as boxes in the margin containing lists of words etc.

Now, the problem I'm having is that when a margin environment occurs just before a page-wide environment, the margin box gets overlapped by the wide environment.

At the moment, we deal with this by hand, moving things around and recompiling the document until we have no more overlaps, but something better would be great.

Is there a way to force the margin box to be on top of anything typeset after it?

or

Can I somehow tell marginpar (or another margin note environment) to avoid having margin notes close to these environments?

Here is a MWE to illustrate the problem:

\documentclass[12pt, a4paper, openleft]{memoir}

\usepackage{blindtext}
\usepackage{environ}% enables you to pass environment contents to a command
\usepackage{tikz}

\usetikzlibrary{%
arrows,%
shapes,%
backgrounds,%
patterns,%
decorations.pathreplacing,%
decorations.pathmorphing,%
decorations.markings,%
shadows,%
shapes.misc,%
calc,%
positioning,%
intersections}

\tikzset{normal border/.style={orange!30!black!10}}
\pgfmathsetseed{1} % To have predictable results

% Start of Boxed Environment
%
% Macro to draw the shape behind the text, when it fits completly in the
% page
\def\WideEnvBoxframe#1{
\tikz{
  \node[inner sep=2em, outer xsep=5cm] (A) {#1};  % Draw the text of the node
  \begin{pgfonlayer}{background}  % Draw the shape behind
  \fill[fill=normalborder] 
        (A.south east) -- (A.south west) -- 
        (A.north west) -- (A.north east) -- cycle;
  \end{pgfonlayer}}}

% Macro to draw the shape, when the text will continue in next page
\def\WideEnvBoxframetop#1{
\begin{tikzpicture}[remember picture]
    \node[inner sep=2em, outer xsep=5cm] (A) {#1};    % Draw the text of the node
  \begin{pgfonlayer}{background}    
  \fill[fill=normalborder]              % Draw the ``complete shape'' behind
        (A.south east) -- (A.south west) -- 
        (A.north west) -- (A.north east) -- cycle;
\end{pgfonlayer}
%   \node[] (empty) at (current page.south west) {};
%     \fill[fill=red]
%           ($ (empty.south east)+(0,2)$) -- ($ (empty.south west)+(0,2)$) -- (empty.south west) -- (empty.south east) -- cycle;   
\end{tikzpicture}
% fill in the white space gap between bottom of frame and footer
   \begin{tikzpicture}[remember picture,overlay]
     \begin{pgfonlayer}{background}   
     \fill[fill=normalborder,opacity=1]
     ($(A.south west)+(-1,0.1)$) rectangle 
     ($(current page.south east)+(2,2.2)$);
     \end{pgfonlayer}
   \end{tikzpicture}
}

% Macro to draw the shape, when the text continues from previous page
\def\WideEnvBoxframebottom#1{
\tikz{
  \node[inner sep=0.2em, outer xsep=5cm, outer ysep=0cm] (A) {#1};   % Draw the text of the node
  \begin{pgfonlayer}{background}   
  \fill[fill=normalborder]             % Draw the ``complete shape'' behind
        (A.south east) -- (A.south west) -- 
        (A.north west) -- (A.north east) -- cycle;
  \end{pgfonlayer}}
% fill in the white space gap between bottom of frame and footer
\begin{tikzpicture}[overlay,remember picture]
  \begin{pgfonlayer}{background}   
  \fill[fill=normalborder,opacity=1]
  ($(current page.north west)+(-3mm,3mm)$) rectangle 
  ($(current page.north east)+(3mm,-2.25cm)$);
  \end{pgfonlayer}
\end{tikzpicture}}

% Macro to draw the shape, when both the text continues from previous page
% and it will continue in next page
\def\WideEnvBoxframemiddle#1{
\begin{tikzpicture}[remember picture]
  \node[inner sep=0.2em, outer xsep=5cm, outer ysep=0cm] (A) {#1};   % Draw the text of the node
  \begin{pgfonlayer}{background}   
  \fill[fill=normalborder]             % Draw the ``complete shape'' behind
        (A.south east) -- (A.south west)  -- 
        (A.north west) -- (A.north east) -- cycle;
   \end{pgfonlayer}
\end{tikzpicture}
% fill in the white space gap between bottom of frame and footer
\begin{tikzpicture}[overlay,remember picture]
  \begin{pgfonlayer}{background}   
   \fill[fill=normalborder,opacity=1]
     ($(A.south west)+(-1,0.1)$) rectangle 
     ($(current page.south east)+(2,0)$);
  \end{pgfonlayer}
\end{tikzpicture}

% fill in the white space gap between top of frame and header
\begin{tikzpicture}[overlay,remember picture]
  \begin{pgfonlayer}{background}   
  \fill[fill=normalborder,opacity=1]
  ([xshift=-3mm, yshift=3mm] current page.north west) rectangle 
  ([yshift=-2.25cm, xshift=3mm] current page.north east);
  \end{pgfonlayer}
\end{tikzpicture}}
% Define the environment which puts the frame
% In this case, the environment also accepts an argument with an optional
% title (which defaults to ``Example'', which is typeset in a box overlaid
% on the top border
\newenvironment{WideEnvBox}[2]{%
\tikzset{normalborder/.style={#2}}
  \def\FrameCommand{\WideEnvBoxframe}%
  \def\FirstFrameCommand{\WideEnvBoxframetop}%
  \def\LastFrameCommand{\WideEnvBoxframebottom}%
  \def\MidFrameCommand{\WideEnvBoxframemiddle}%
  \MakeFramed {\FrameRestore}
%\needspace{9\baselineskip}
{#1}\par
}%
{\endMakeFramed}

\definecolor[named]{activity}{HTML}{E1E6D1}

\newenvironment{Activity}[1]{%
\colorlet{normalborder}{activity}
\begin{WideEnvBox}{\sffamily\large\textbf{ACTIVITY:} #1}{activity}%
}{%
\end{WideEnvBox}%
}
% End of Boxed Environment
%
% Margin box
%
\definecolor[named]{newwords}{HTML}{FCD2C1}

\tikzstyle{newwordsblock} = [rectangle, fill=newwords, text badly centered, text width=2.5cm, rounded corners=10pt, draw=black, very thick]

\NewEnviron{NoteNewwords}{%
\marginpar{\begin{tikzpicture}
    \node[] (text) [newwordsblock]
{\vskip1mm\small\textbf{New Words}\vskip2mm\hrule\vspace{3mm}\scriptsize\BODY\vspace{3mm}};
    \node[below=0.5cm of text] (dummytext) [newwordsblock] {\vspace{50mm}};
\end{tikzpicture}}%
}

\begin{document}

\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}

\begin{NoteNewwords}
\blindlist{itemize}[6]
\end{NoteNewwords}

\begin{Activity}{Example}
\blindtext[3]
\end{Activity}

\end{document}

margin box is underneath page-wide environment

5
  • 1
    Can you just send the large fill to the background layer ? – percusse Jun 5 '13 at 10:22
  • The green filled background can start midway on a page and end midway on another page, so I cannot just fill the entire page with a colour. – ezietsman Jun 5 '13 at 11:22
  • TikZ has a layering mechanism. Look up pgfdeclarelayer in the manual. You can put the margin stuff in a "foreground" layer, or the green box in a "background" layer. – John Wickerson Jun 5 '13 at 12:20
  • I have tried this (and the MWE above shows that), I think the issue is that the layers only apply to a single tikzpicture environment, I'm not sure one can define a global document-wide layer (which is exactly what I need) i.e. stuff on the foreground layer is always above stuff in the background layer, regardless of where and when they were typeset. – ezietsman Jun 5 '13 at 12:26
  • I would try the mdframed package if it fits my needs. – Malipivo Apr 4 '14 at 20:02
3

Like this:

enter image description here

Well, layers work only inside a single tikzpicture environment, and drawing more than one thing on the main layer is impossible. So, drawing takes the natural order in which the commands have been written; here you enter the markup for the marginbox, then the markup for the page-wide environment, so the latter covers the first.

The solution I suggest here is to delay drawing the marginbox after drawing the page-wide environment. But first, calculate the correct position to insert the box later. Here is the command and the modified environment for this:

\newcommand{\tikzmark}[1]{\tikz[remember picture] \coordinate (#1);}

\NewEnviron{NoteNewwords}[1]{%
\begin{tikzpicture}[remember picture,overlay]
    \node (text) at (#1) [newwordsblock,anchor=north west]
    {\vskip1mm\small\textbf{New Words}\vskip2mm\hrule\vspace{3mm}\scriptsize%
    \BODY%
    \vspace{3mm}};
    \node[below=0.5cm of text] (dummytext) [newwordsblock] {\vspace{50mm}};
\end{tikzpicture}}%

When called, the \tikzmark command will save the current coordinates, so if we issue:

\marginpar{\tikzmark{here}}

this means that we put a mark in the \marginpar at the current insertion point. Next, after the page-wide environment is drawn, we can call the marginbox environment with the extra argument of position information:

\begin{NoteNewwords}{here}
\blindlist{itemize}[6]
\end{NoteNewwords}

Here is the complete code:

\documentclass[12pt, a4paper, openleft]{memoir}
\usepackage{blindtext}
\usepackage{environ}% enables you to pass environment contents to a command
\usepackage{tikz}

\usetikzlibrary{%
arrows,%
shapes,%
backgrounds,%
patterns,%
decorations.pathreplacing,%
decorations.pathmorphing,%
decorations.markings,%
shadows,%
shapes.misc,%
calc,%
positioning,%
intersections}

\tikzset{normal border/.style={orange!30!black!10}}
\pgfmathsetseed{1} % To have predictable results


% Start of Boxed Environment
%
% Macro to draw the shape behind the text, when it fits completly in the
% page
\def\WideEnvBoxframe#1{
\tikz{
  \node[inner sep=2em, outer xsep=5cm] (A) {#1};  % Draw the text of the node
  \begin{pgfonlayer}{background}  % Draw the shape behind
  \fill[fill=normalborder] 
        (A.south east) -- (A.south west) -- 
        (A.north west) -- (A.north east) -- cycle;
  \end{pgfonlayer}}}

% Macro to draw the shape, when the text will continue in next page
\def\WideEnvBoxframetop#1{
\begin{tikzpicture}[remember picture]
    \node[inner sep=2em, outer xsep=5cm] (A) {#1};    % Draw the text of the node
  \begin{pgfonlayer}{background}    
  \fill[fill=normalborder]              % Draw the ``complete shape'' behind
        (A.south east) -- (A.south west) -- 
        (A.north west) -- (A.north east) -- cycle;
\end{pgfonlayer}
%   \node[] (empty) at (current page.south west) {};
%     \fill[fill=red]
%           ($ (empty.south east)+(0,2)$) -- ($ (empty.south west)+(0,2)$) -- (empty.south west) -- (empty.south east) -- cycle;   
\end{tikzpicture}
% fill in the white space gap between bottom of frame and footer
   \begin{tikzpicture}[remember picture,overlay]
     \begin{pgfonlayer}{background}   
     \fill[fill=normalborder,opacity=1]
     ($(A.south west)+(-1,0.1)$) rectangle 
     ($(current page.south east)+(2,2.2)$);
     \end{pgfonlayer}
   \end{tikzpicture}
}

% Macro to draw the shape, when the text continues from previous page
\def\WideEnvBoxframebottom#1{
\tikz{
  \node[inner sep=0.2em, outer xsep=5cm, outer ysep=0cm] (A) {#1};   % Draw the text of the node
  \begin{pgfonlayer}{background}   
  \fill[fill=normalborder]             % Draw the ``complete shape'' behind
        (A.south east) -- (A.south west) -- 
        (A.north west) -- (A.north east) -- cycle;
  \end{pgfonlayer}}
% fill in the white space gap between bottom of frame and footer
\begin{tikzpicture}[overlay,remember picture]
  \begin{pgfonlayer}{background}   
  \fill[fill=normalborder,opacity=1]
  ($(current page.north west)+(-3mm,3mm)$) rectangle 
  ($(current page.north east)+(3mm,-2.25cm)$);
  \end{pgfonlayer}
\end{tikzpicture}}

% Macro to draw the shape, when both the text continues from previous page
% and it will continue in next page
\def\WideEnvBoxframemiddle#1{
\begin{tikzpicture}[remember picture]
  \node[inner sep=0.2em, outer xsep=5cm, outer ysep=0cm] (A) {#1};   % Draw the text of the node
  \begin{pgfonlayer}{background}   
  \fill[fill=normalborder]             % Draw the ``complete shape'' behind
        (A.south east) -- (A.south west)  -- 
        (A.north west) -- (A.north east) -- cycle;
   \end{pgfonlayer}
\end{tikzpicture}
% fill in the white space gap between bottom of frame and footer
\begin{tikzpicture}[overlay,remember picture]
  \begin{pgfonlayer}{background}   
   \fill[fill=normalborder,opacity=1]
     ($(A.south west)+(-1,0.1)$) rectangle 
     ($(current page.south east)+(2,0)$);
  \end{pgfonlayer}
\end{tikzpicture}

% fill in the white space gap between top of frame and header
\begin{tikzpicture}[overlay,remember picture]
  \begin{pgfonlayer}{background}   
  \fill[fill=normalborder,opacity=1]
  ([xshift=-3mm, yshift=3mm] current page.north west) rectangle 
  ([yshift=-2.25cm, xshift=3mm] current page.north east);
  \end{pgfonlayer}
\end{tikzpicture}}
% Define the environment which puts the frame
% In this case, the environment also accepts an argument with an optional
% title (which defaults to ``Example'', which is typeset in a box overlaid
% on the top border
\newenvironment{WideEnvBox}[2]{%
\tikzset{normalborder/.style={#2}}
  \def\FrameCommand{\WideEnvBoxframe}%
  \def\FirstFrameCommand{\WideEnvBoxframetop}%
  \def\LastFrameCommand{\WideEnvBoxframebottom}%
  \def\MidFrameCommand{\WideEnvBoxframemiddle}%
  \MakeFramed {\FrameRestore}
%\needspace{9\baselineskip}
{#1}\par
}%
{\endMakeFramed}

\definecolor[named]{activity}{HTML}{E1E6D1}

\newenvironment{Activity}[1]{%
\colorlet{normalborder}{activity}
\begin{WideEnvBox}{\sffamily\large\textbf{ACTIVITY:} #1}{activity}%
}{%
\end{WideEnvBox}%
}
%
% End of Boxed Environment
%

%
%  Margin box
%
\definecolor[named]{newwords}{HTML}{FCD2C1}

\tikzstyle{newwordsblock} = [rectangle, fill=newwords, text badly centered, text width=2.5cm, rounded corners=10pt, draw=black, very thick]

\newcommand{\tikzmark}[1]{\tikz[remember picture] \coordinate (#1);}

\NewEnviron{NoteNewwords}[1]{%
\begin{tikzpicture}[remember picture,overlay]
    \node (text) at (#1) [newwordsblock,anchor=north west]
    {\vskip1mm\small\textbf{New Words}\vskip2mm\hrule\vspace{3mm}\scriptsize%
    \BODY%
    \vspace{3mm}};
    \node[below=0.5cm of text] (dummytext) [newwordsblock] {\vspace{50mm}};
\end{tikzpicture}}%

\begin{document}

\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}

\marginpar{\tikzmark{here}}

\begin{Activity}{Example}
\blindtext[3]
\end{Activity}

\begin{NoteNewwords}{here}
\blindlist{itemize}[6]
\end{NoteNewwords}



\end{document}

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.