[Tex/LaTex] Color gradient as background in margins

backgroundsgradient

Currently I am using an external PDF image to get a color gradient provide in the margins. See the output below. I achieve this by using command \ULCornerWallPaper{1}{./pictures/wallpaper_1.pdf}

However, this method is very inefficient because importing the external picture every time results in a long compilation time. Is there a better way of doing it?

The gradient is only applied to some of the pages so it would be ideal if you provided me with a solution which I can include in \ULCornerWallPaper{1}{} so I can undo gradient after a while using command \ClearWallPaper.

Could I achieve this using tikz? I'm not very familiar with it, but it looks like a possible tool for solving my problem.

two muppets

Best Answer

The solution below defines two alternative ways of drawing a coloured gradient in the margin background on a selection of pages:

  1. Invoke the \conditionalmarginbg (which takes no argument) at the beginning of your document and then toggle the margin background on/off in your document by using the \startdrawmarginbg and \stopdrawmarginbg macros.
  2. Invoke \marginbgpagelist at the beginning of your document; its only argument is a list of pages on which to draw a margin background. That list uses pgffor's \foreach syntax, so you can specify 10,...,20 to draw a margin back on pages 10 to 20.

In the example below, I used \conditionalmarginbg and, for visualisation, I emphasised (red, bold text) where \startdrawmarginbg and \stopdrawmarginbg are invoked.

Notes:

  • You'll need to run pdflatex no fewer than 3 times to get the correct output.
  • I presume you need(ed) this for a book, so I didn't bother making my solution compatible with the oneside class option. It works fine with twoside, though.

References:

enter image description here enter image description here

\documentclass[twoside]{book}

\usepackage{lipsum}                         % for filler text
\usepackage[margin=3cm]{geometry}           % for setting the dimensions
\usepackage{tikzpagenodes}                      
\usepackage{background}
    \backgroundsetup%
    {%
        contents    = {},%
        opacity     = 1,%
        scale       = 1,
    }
\usepackage{etoolbox}                       % defines the \ifnumodd macro
\usepackage{xcolor}



% Let's define some colours for this colour gradient
\definecolor{outercolor}{gray}{.7}
\definecolor{innercolor}{gray}{1}

% a switch for toggling margin background on/off
\newif\ifdrawmarginbg\drawmarginbgfalse
\newcommand\startdrawmarginbg{\drawmarginbgtrue}
\newcommand\stopdrawmarginbg{\drawmarginbgfalse}

% redefinition of \emph, just to show where
% my \startdrawmarginbg and \stopdrawmarginbg are invoked in the example
\renewcommand\emph[1]{\textcolor{red}{\bfseries#1}}


% ----- Two possible strategies -----

% --- \conditionalmarginbg ---
% Invoke the following macro at the beginning of the document and then
% use \startdrawmarginbg and \stopdrawmarginbg to toggle the margin background
% gradient on/off in the document.
\newcommand\conditionalmarginbg%
{%
    \AddEverypageHook%
    {%
        \ifdrawmarginbg%
            \thispagemarginbg%
        \fi%
    }%
}

% --- \marginbgpagelist ---
% Invoke the following macro at the beginning of the document.
% It's only (mandatory) argument is a list (using pgffor's \foreach syntax)
% corresponding to the pages on which a margin background gradient
% should be drawn.
\newcommand\marginbgpagelist[1]%
{%
    \AddEverypageHook%
    {%
        \foreach \p in {#1}%
        {%
            \ifnum\value{page}=\p%
                \thispagemarginbg%
            \fi
        }%
    }%
}


% ----- Auxiliary macros ----- 

% Auxiliary macro for both \conditionalmarginbg and \marginbgpagelist
\newcommand\thispagemarginbg
{%
    \ifnumodd{\value{page}}
        {\marginbgevenorodd{1}}
        {\marginbgevenorodd{0}}
    \BgMaterial
}%

% Auxiliary macro for \thispagemarginbg
\newcommand\marginbgevenorodd[1]%
{%
    \ifnum#1=1%
        \def\shadeangle{90}
        \def\marginrectangle
        {%
            (current page marginpar area.south west |- current page.south)%
            rectangle%
            (current page.north east)
        }
    \else%
        \ifnum#1=0%

            \def\shadeangle{-90}
            \def\marginrectangle
            {%
                (current page marginpar area.south east |- current page.south)%
                rectangle%
                (current page.north west)
            }
        \else%
            \errmessage{Incompatible value supplied to \string\marginbgevenorodd}   
        \fi%
    \fi%
    \backgroundsetup
    {%
        angle=0,%
        contents=%
        {%
            \tikz[remember picture,overlay]
            \shade
            [%
                bottom color    = outercolor,%
                top color       = innercolor,%
                shading angle   = \shadeangle,%
            ] \marginrectangle;%
        }%                  
    }%
}

% Use either...
% \marginbgpagelist{2,3,...,4}
% or...
\conditionalmarginbg

\begin{document} 

\lipsum[1-10]

\emph{A margin background gradient is drawn from this page onwards.}
\startdrawmarginbg

\lipsum[21-40]

\emph{No margin background gradient is drawn from this page onwards.}
\stopdrawmarginbg

\lipsum[41-50]

\end{document}
Related Question