36

I have to typeset a book that contains a lot of side material (comments, notes, references, supplementary explanations, ...) that I want to appear alongside the main material.

At first, I thought of using the tufte-latex class, which reserves quite a large space for margin notes. Unfortunately, I have to use a b5 paper size, which does not allow for too large margin notes. Also, I do not like that when there are no margin notes, there would be a lot of "white" space on the page.

My idea was to create a type of "side note" that will share the same space with the main text where the note is issued, such that:

  • each paragraph together with all of its side notes will be typeset similar to a two-columns layout;
  • the side notes will appear in the right column; the main text will appear in the left column;
  • the side note should be typeset using a smaller font size;
  • each side note will be typeset in its one "box" over a colored background, and the color can be specified for each note independently;
  • the distribution of the width of the two columns should be computed for each paragraph, depending on the ration between the main text and the side text, such that one obtains the right balance, meaning that:
    • if there are no side notes, the paragraph should be typeset using the full text width;
    • if there are side notes, the width of the right column that contains the side notes should be between a minimum (e.g., 0.3\textwidth) and a maximum (e.g., 0.5\textwidth) value;
    • the height of the right column should not exceed the height of the left column;
    • no side note should break across pages;
    • if the previous criteria can not be satisfied, then the side notes should appear right after the main text, using the full text width (it may break across pages)

I know that I ask too much, and maybe this should be a package, but these were the criteria that I thought would give a good result for my book.

Unfortunately, I don't have enough "TeXperience" to achieve this task, so any help is much appreciated.

Edit: Here is a sample of what I have in mind. It may very well contain a lot of maths.

sample file

  • 11
    IMO it IS a request for a package indeed... :) – Count Zero Jun 15 '13 at 12:07
  • 1
    ... and I'd love to see a package like this! With the added feature of globally disabling the notes with a package option. – Count Zero Jun 15 '13 at 12:21
  • 2
    Not quite what you ask for but I'd start by looking at wrapfig package. – David Carlisle Jun 15 '13 at 17:59
  • 2
    Why not marginnote (or wrapfig) package and a new definition of boxes using mdframed or tcolorbox? – cacamailg Jun 17 '13 at 14:36
12

I do realize that this is not a full solution, but it might at least be a partial solution. It does not do the following:

  • No color is used
  • No notes are typeset in full text width
  • There are no bounds for how much of the horisontal space is occupied with notes
  • There are no handling of notes close to or across page breaks (every paragraph with a note automatically starts at a new page, and this problem can probably not be fixed within a table environment, as I used, since no table environment can break pages automatically inside a cell)

Also, there is something wrong with the numbering of the notes, which I guess is a result of something in the inner workings of the tabulary package (it seems that the command is called twice), but hopefully someone a bit more skilled than me can find the error.. :)

EDIT: There was an error in the tabulary package, which is fixed in the code below. (With the help of David Carlisle


EDIT: I made a fix to make the number in the beginning of the note matching the number where the note was made look like the corresponding numbers in footnotes. I also added the possibility to change the color of a note.


\documentclass[]{article}


\usepackage{tabulary} % used for automatic adjustment of column width
\usepackage[newcommands]{ragged2e} % ragged text and allow hyphenation
\usepackage{array} % for specifying the padding for the tabulary table
\tymin=0.1\textwidth % settings for the tabulary package
\tymax=10\textwidth
\renewcommand{\tabcolsep}{0cm}
\newcommand{\colspace}{1em}
\AtBeginDocument{\edef\normalparindent{\the\parindent}} % saved the parindent to allow it to be mimicked inside the tabulary environment

\usepackage{newfile} % for enabling writing to a file
\newwrite\tempfile


\makeatletter

% A long hack to fix a bug in the tabulary package
\def\endtabulary{%
  \gdef\@halignto{}%
  \def\@elt##1{\global\value{##1}\the\value{##1}\relax}%
  \edef\TY@ckpt{\cl@@ckpt}%
  \expandafter\TY@tab\the\toks@
  \crcr\omit
  {\xdef\TY@save@row{}%
     \loop
    \advance\TY@count\m@ne
    \ifnum\TY@count>\z@
    \xdef\TY@save@row{\TY@save@row&\omit}%
    \repeat}\TY@save@row
  \endarray\global\setbox1=\lastbox\setbox0=\vbox{\unvbox1
    \unskip\global\setbox1=\lastbox}\egroup
  \dimen@\TY@linewidth
  \divide\dimen@\TY@count
  \ifdim\dimen@<\tymin
    \TY@warn{tymin too large (\the\tymin), resetting to \the\dimen@}%
    \tymin\dimen@
  \fi
  \setbox\tw@=\hbox{\unhbox\@ne
    \loop
\@tempdima=\lastskip
\ifdim\@tempdima>\z@
   \global\advance\TY@linewidth-\@tempdima
\fi
    \unskip
    \setbox\tw@=\lastbox
    \ifhbox\tw@
      \ifdim\wd\tw@>\tymax
        \wd\tw@\tymax
      \fi
  \TY@width\dimen@
  \advance\dimen@\wd\tw@
   \TY@width\xdef{\the\dimen@}%
      \ifdim\dimen@<\tymin
         \global\advance\TY@linewidth-\dimen@
         \expandafter\xdef\csname TY@F\the\TY@count\endcsname
                                                        {\the\dimen@}%
       \else
      \expandafter\ifx\csname TY@F\the\TY@count\endcsname\z@
         \global\advance\TY@linewidth-\dimen@
         \expandafter\xdef\csname TY@F\the\TY@count\endcsname
                                                        {\the\dimen@}%
        \else
         \global\advance\TY@tablewidth\dimen@
         \global\expandafter\let\csname TY@F\the\TY@count\endcsname
                                                               \maxdimen
       \fi\fi
       \advance\TY@count\m@ne
    \repeat}%
    \TY@checkmin
    \TY@checkmin
    \TY@checkmin
    \TY@checkmin
    \TY@count\z@
    \let\TY@box\TY@box@v
  \TY@ckpt
  {\expandafter\TY@final\the\toks@\endTY@final}%
  \count@\z@
  \@tempswatrue
  \@whilesw\if@tempswa\fi{%
  \advance\count@\@ne
  \expandafter\ifx\csname TY@SF\the\count@\endcsname\relax
    \@tempswafalse
  \else
    \global\expandafter\let\csname TY@F\the\count@\expandafter\endcsname
                   \csname TY@SF\the\count@\endcsname
    \global\expandafter\let\csname TY@\the\count@\expandafter\endcsname
                   \csname TY@S\the\count@\endcsname
  \fi}%
  \TY@linewidth\@ovxx
  \TY@tablewidth\@ovyy
    \ifnum0=`{\fi}}




\newcounter{localsidenotecounter} % defines a counter for the notes
\usepackage{color} % for coloring the notes

\newcommand{\sidenote}[2][black]
{%
\stepcounter{localsidenotecounter} % increases the counter by one
${}^\textrm{\footnotesize\arabic{localsidenotecounter}}$ % formats the small number to be put in the text to mark the existance of a note
\immediate\write\tempfile % saves the note with some of its formatting to a file
{
\noexpand\textcolor{#1}{${}^{\arabic{localsidenotecounter}}$ #2}


\noexpand\vspace{0.5em} % adds some space between the notes
}%
}

\newcommand{\sidenotepc}[1] % defines a command for paragraphs with notes
{ % sets some settings for the table
\noindent \begin{tabulary}{\textwidth}{>{\setlength\parindent{\normalparindent} \immediate\openout\tempfile=sidenotes.tex }J<{\immediate\closeout\tempfile}@{\hspace{\colspace}}>{
\footnotesize \input{sidenotes.tex} 
}J}
#1 & \end{tabulary}
}

\makeatother


\begin{document}


\sidenotepc{
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue\sidenote{Test} pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure\sidenote[red]{Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure}\sidenote{Blaha}.
}

\sidenotepc{
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue\sidenote{Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure} pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure\sidenote{Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure}
}


\end{document}

Example

  • Could you, please, explain a bit the code (or your approach), such that I can pick up with the remaining requirements? – digital-Ink Jun 17 '13 at 17:00
  • 2
    I tried to use the tabulary package since it already has the functionality to adjust the size of the columns according to the amount of text in them, so that I did not have to solve that problem myself. Most of the code are actually only a bug fix to the tabulary package, so the only thing you might want to take a closer look at is at the definitions of the commands \sidenote and \sidenotepc. The idea is to collect all notes in a separate file from which we then collect the notes. Unfortunately this restricts the amount of commands which it is possible to use inside the notes ... – malin Jun 17 '13 at 19:17
  • Look especially at where the arguments of these two commands go :) – malin Jun 17 '13 at 19:33
11

EDIT: I've updated the solution below to use the wrapfig environment, which simplified at least some parts of the code. This solved all the spacing issues I had before. I also changed the definition of the command to only require that it is put before each paragraph, and added functionality for putting long notes on new lines. The only issues remaining is that the solution still does not work well with page breaks, and also that it is quite cumbersome to but the same command before each paragraph, even if it is less cumbersome than the syntax of my previous solution.


I've now made a new solution (with the help of David Carlise) which I think is a bit closer to what you intended than my last attempt. It still has some problems though:

  • Some unwanted spaces sometimes appear between paragraphs
  • Notes are never put on separate lines
  • No sidebreaks are allowed inside paragraphs

The result now look as in the image below: example result

And the source code.. :)

    \documentclass[10pt]{article}


% Packages
\usepackage[newcommands]{ragged2e}
\usepackage{newfile}
\usepackage{color}
\usepackage{xparse}
\usepackage{graphics}
\usepackage[dvipsnames]{xcolor}
\usepackage{hyperref}
\usepackage{wrapfig}
\usepackage{ifthen}

% Settings
\colorlet{Pbardefault}{yellow!70} % Default color for the colored bar left to the notes
\colorlet{Plightdefault}{yellow!10}% Default color for background of the note
\def\Pmin{0.5} % ~minimal amount main text
\def\Pmax{0.95} % ~maximal amount main text / \Psf
\def\Psf{1.14} % 


\newcounter{localsidenotecounter}
\newlength{\currentparskip}
\setlength{\currentparskip}{\parskip}


% The formatting of the note
\newdimen\Pparsep
\Pparsep=0.2em

\newdimen\Pcolorwidth
\Pcolorwidth=2mm


% The paragraph command
\makeatletter
\def\sidenotepi#1\par%
{
%
\immediate\openout\tempfile=sidenotes.tex %
%
\twopara%
{
#1   \immediate\closeout\tempfile 
}
{\input{sidenotes.tex}}
}

\makeatother




% A command for finding the optimal text widths
\makeatletter

\long\def\twopara#1#2{%

\newdimen\columnsep
\columnsep=\dimexpr \Pparsep + \Pcolorwidth

 \def\@elt##1{\global\value{##1}\the\value{##1}\relax}% 
\edef\TY@ckpt{\cl@@ckpt}%

\@tempdima\dimexpr\textwidth-\columnsep\relax
{\hbadness\@M\raggedright\hsize.5\@tempdima \@tempdima\hsize
\setbox\z@\vbox{{#1\endgraf}}%
\setbox\tw@\vbox{{#2\endgraf}}%
\Gscale@div\tmp{\ht\z@}{\dimexpr\ht\z@+\ht\tw@\relax}%
\global\let\xtmp\tmp}%
\dimen@ \xtmp\@tempdima
\ifdim\dimen@<\Pmin\@tempdima \dimen@\Pmin\@tempdima\fi
\ifdim\dimen@>\Pmax\@tempdima \dimen@\Pmax\@tempdima\fi
\dimen@ii\dimexpr\@tempdima-\dimen@\relax 

\TY@ckpt


\ifdim\dimen@ii<20pt
  #1
\else
  \ifdim \Psf\dimen@ii>\dimexpr\textwidth-\Pmin\textwidth
    #1
    \let\Pnotebox\Pnotebox@
    \dimen@ii = \dimexpr \textwidth-4mm
      \setlength{\intextsep}{2pt}%
      \begin{figure}[h]
          #2
      \end{figure}
  \else

      \let\Pnotebox\Pnotebox@
      \dimen@ii\dimexpr\Psf\dimen@ii
      \setlength{\intextsep}{0pt}%
      \begin{wrapfigure}{o}[-4mm]{\dimen@ii}
          #2
      \end{wrapfigure}
      #1
      \fi
  \fi

\let\Pnotebox\Pnotebox@@
}
\makeatother



% The unformatted note text
\makeatletter
\long\def\Pnotebox@@#1#2#3{ %barcolor, backcolor, text
#3}
\makeatother

\makeatletter
\long\def\Pnotebox#1#2#3{ %barcolor, backcolor, text
#3}
\makeatother

% The formatting of the notes
\makeatletter
\newdimen\Pnoteheight
\long\def\Pnotebox@#1#2#3{ %barcolor, backcolor, text
\settoheight{\Pnoteheight}{\parbox{\dimen@ii}{#3}}%
\begin{minipage}{\dimexpr\dimen@ii+\Pcolorwidth}
  \textcolor{#1}{\rule[\dimexpr-\Pnoteheight+1mm]{\Pcolorwidth}{\dimexpr 2\Pnoteheight}}%
  \colorbox{#2}{\parbox{\dimen@ii}{#3}}
\end{minipage}%
}
\makeatother



% Commands for making the sidenote

\newwrite\tempfile

\makeatletter

\DeclareDocumentCommand \sidenote {m O{Pbardefault} O{Plightdefault}} {%
\stepcounter{localsidenotecounter}%
\hyperlink{sidenote\arabic{localsidenotecounter}}{${}^\textrm{\footnotesize\arabic{localsidenotecounter}}$}%
\immediate\write\tempfile%
{%
\noexpand\Pnotebox{#2}{#3}{%
\noexpand\footnotesize \noexpand{\noexpand\hypertarget{sidenote\arabic{localsidenotecounter}}{${}^{\arabic{localsidenotecounter}}$} \unexpanded{#1 }}%
}}}
\makeatother



\begin{document}





\sidenotepi
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue\sidenote{Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure} pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure


\sidenotepi
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure.


\sidenotepi
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue\sidenote{Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure} pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure.\sidenote{Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure.}[blue][blue!5]

\end{document}
  • Would it be possible to have only the \sidenote command? Meaning that the existence of a \sidenote would automatically generate the desired layout, without including every paragraph inside a \sidenotepi. – digital-Ink Jun 23 '13 at 7:18
  • I guess so, but I don't know how – malin Jun 23 '13 at 14:53
  • 1
    @digital-Ink I've now improved on the solution so that it only requires the command to be put before paragraph, to at least remove the brackets around paragraphs which was needed earlier. – malin Jul 2 '13 at 9:25
  • Smooth! Thanks for the solution! Real good work! – kxk Jun 2 '18 at 21:30
8

Here you have a flavor of what you can do with wrapfig and tcolorbox. I didn't have time now to improve it, nevertheless you can play around and read the documentation to adapt it to your needs

\documentclass{article}

\usepackage{xcolor}
\usepackage{wrapfig}
\usepackage{setspace} % set space between lines
\usepackage{ragged2e} % ragged text and allow hyphenation
\usepackage{environ} % new environment
\usepackage{tcolorbox} % colorful boxes

\usepackage{blindtext} % just for testing

\usepackage{hyperref}

\newcounter{notecounter} % counter for notes
\NewEnviron{enote}
{%
    \refstepcounter{notecounter} % increment note counter
    \begin{singlespace} % single space at notes (optional)
    \begin{tcolorbox}[%
        colframe=red!50!yellow!50!black, 
        colback=red!50!yellow!5!white,
        coltitle=red!50!yellow!3!white,
        fonttitle=\small\sffamily\bfseries,
        fontupper=\small,
        fontlower=\small,
        left=0mm,
        right=0mm,
        top=0mm,
        bottom=0mm,
        middle=2pt,
        boxsep=1mm,
        arc=0mm,
        boxrule=0.5pt,
        leftrule=3mm,
        %title=Note~\thenotecounter\label{note:\thenotecounter}
    ]
        \noindent Note~\thenotecounter\label{note:\thenotecounter}
    \tcblower
        \sloppy\hyphenchar\font=\defaulthyphenchar\RaggedRight\BODY
    \end{tcolorbox}
    \end{singlespace}
}

\newcommand{\sidenote}[3]{%
    \setlength{\wrapoverhang}{\marginparwidth}%
    %\setlength{\columnsep}{0pt}%
    \addtolength{\wrapoverhang}{\marginparsep}%
    \begin{wrapfigure}{o}{#1}%
    \begin{enote}%
        #2
    \end{enote}%
    \end{wrapfigure}
    #3$^\textrm{\scriptsize\ref{note:\thenotecounter}}$}

\begin{document}

\sidenote{10cm}{%
    side side side side side side side side side
    side side side side side side side side side
    side side side side side side side side side
    side side side side side side side side side
    side side side side side side side side side
    side side side side side side side side side
    }{%
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    }

\blindtext

\sidenote{0.8\textwidth}{%
    side side side side side side side side side
    side side side side side side side side side
    side side side side side side side side side
    side side side side side side side side side
    side side side side side side side side side
    side side side side side side side side side
    }{%
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    text text text text text text text text text
    }
\end{document}

enter image description here

  • Is there a work-around for when the notes are near the bottom of the page and extend down past the footer, when they don't split between pages? – elika kohen Oct 12 at 7:47

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.