Color gradient as background in margins

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:

  • Claudio Fiandrino's answer to How to set colored ruled margins for different pages?

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}

I will provide a solution which draws the gradient using MetaFun. It's drawn on the page layer, which means it is located underneath the text elements and margin notes. You can also use leftpage or rightpage to include different backgrounds on even and odd pages.

Since MetaPost is much faster than TikZ or including external figures you don't have worry about the compilation times. The uniqueMPgraphic ensures that the graphic is computed only once and reused. This enables to draw 1000 pages with gradient background in about 2.5s (on my machine).

The location is customisable via the option gradientmargin. Here's a complete example using ConTeXt.

\setuplayout [width=13cm]

\startuniqueMPgraphic{background:gradient}
  path p;
    p := OverlayBox leftenlarged -\framedparameter{gradientmargin};
    linear_shade(p, 0, white, OverlayColor);
  setbounds currentpicture to boundingbox OverlayBox;
\stopuniqueMPgraphic

\defineoverlay
  [background:gradient]
  [\uniqueMPgraphic{background:gradient}]

\setupbackgrounds
  [page]
  [background=background:gradient,
   gradientmargin=15cm,
   backgroundcolor=middlegray]

\starttext
  \dorecurse{10}{\input knuth}
\stoptext

Result:

result