[Tex/LaTex] Tufte alike design with sidenotes crossing pagebreaks, or: Tufte made with KOMA-Script

koma-scriptsidenotestufte

As far as I understand (correct me if I'm wrong), a disadvantage of the tufte classes is that the side notes can not cross a page break. The side notes have to end on the very page where they begin.

I realized that a fairly current version of KOMA-Script includes a package scrlayer-notecolumn, which solves this issue: we can have side notes independently from page breaks.

The side notes even work inside floats, but the numbering of the side notes is an issue then.

We can have tabulars and figures in the margin, but each command in the margin needs a \protect.

Question: How to write an environment margintabular like in the tufte classes? What more do we need to improve Tufte style documents with the scrlayer-notecolumn package?

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{scrlayer-scrpage, scrlayer-notecolumn, lmodern, blindtext,
ragged2e}

%% step 1: counter
\newcounter{snmark}
\setcounter{snmark}{0}


%% step 2: hanging sidenotes, definition from tugboat
\makeatletter
\newcommand*{\hangfrom}[1]{%
  \setbox\@tempboxa\hbox{{#1}}%
  \hangindent \wd\@tempboxa
  \noindent\box\@tempboxa}
\makeatletter

%% step 3: define sidenote marks in the text
\newcommand{\makesidenotemark}{%
  \textsuperscript{\thesnmark}
}%


%% step 4: and now the definition of sidenotes
\newcommand{\sidenote}[1]{%
  \refstepcounter{snmark}% Zähler erhöhen
  \makesidenotemark{}% Nummer im Text setzen.
  \makenote[paragraphs]{%
    \hangfrom{%
      \makebox[1em][l]{%
        \thesnmark}
            }
        \protect\RaggedRight{} #1}% Text setzen im Rand
}


%% this is, except for the values (».7«) from scrguide.pdf to define
%% the notecolumn.

\newlength{\paragraphscolwidth}
\AfterCalculatingTypearea{%
\setlength{\paragraphscolwidth}{.4\textwidth}%
\addtolength{\paragraphscolwidth}{-\marginparsep}%
}
\recalctypearea
\DeclareNewNoteColumn[%
position=\oddsidemargin+1in
+.7\textwidth
+\marginparsep,
width=\paragraphscolwidth,
font=\footnotesize
]{paragraphs}





%% Delete all sidenotes:
%\renewcommand{\sidenote}[1]{\relax}

\begin{document}
\begin{addmargin}[0pt]{.3\textwidth}
  This is the text with a \sidenote{See here.\blindtext}.
  \blindtext


  And here we have a second paragraph and a second
  sidenote\sidenote{\blindtext}.
  \blindtext

  And this is the big hit: We can have sidenotes which include
  pagebreaks!\sidenote{Proof of concept: \blindtext{}}


  \syncwithnotecolumns[paragraphs]

      And now we somewhere have a table:
  \begin{table}[b]
    \centering
    \begin{tabular}{ll}
      Proof\sidenote{From inside the float} & of concept\\
    \end{tabular}
    \caption{This is a table}
    \label{tab:table}
  \end{table}

Besides that, we even can have tabulars in the margin\sidenote{%
  Tabular in the margin:

  \protect\begin{tabular}{|l|l|}\protect\hline
    a& b\\\protect\hline
    a& b\\\protect\hline
    a& b\\\protect\hline
  \protect\end{tabular}
}, but they have
to be narrow and well protected.

\end{addmargin}


\end{document}

Best Answer

To have tables inside the margin note, you could make a kind of non floating table environment, e.g.

\usepackage{environ}
\makeatletter
\NewEnviron{margintable}{%
  \expandafter\@margintable\expandafter{\BODY}%
}
\newcommand*\@margintable[1]{%
  \makenote[paragraphs]{%
    \protect\begin{nonfloattable}\detokenize{#1}\protect\end{nonfloattable}
  }%
}
\newenvironment{nonfloattable}{%
  \par\noindent\begin{minipage}{\linewidth}
    \def\@captype{table}%
}{%
  \end{minipage}\par
}

But there is a problem: It seems that writing a label to the aux-file from within a note does not work, so \label{tab:secondtable} inside a margintable environment would not result in a label.

Strange: Writing the caption into the aux file does work.

I currently do not know why writing the label to the aux file does not work but writing the lot entry into the aux file does work. Nevertheless, you could use a hack to write the label information into the aux-file when using margintable instead of when making the note:

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{scrlayer-scrpage, scrlayer-notecolumn, lmodern, blindtext,
ragged2e}

%% step 1: counter
\newcounter{snmark}
\setcounter{snmark}{0}


%% step 2: hanging sidenotes, definition from tugboat
\makeatletter
\newcommand*{\hangfrom}[1]{%
  \setbox\@tempboxa\hbox{{#1}}%
  \hangindent \wd\@tempboxa
  \noindent\box\@tempboxa}
\makeatletter

%% step 3: define sidenote marks in the text
\newcommand{\makesidenotemark}{%
  \textsuperscript{\thesnmark}
}%


%% step 4: and now the definition of sidenotes
\newcommand{\sidenote}[1]{%
  \refstepcounter{snmark}% Zähler erhöhen
  \makesidenotemark{}% Nummer im Text setzen.
  \makenote[paragraphs]{%
    \hangfrom{%
      \makebox[1em][l]{%
        \thesnmark}
            }
        \protect\RaggedRight{} #1}% Text setzen im Rand
}


%% this is, except for the values (».7«) from scrguide.pdf to define
%% the notecolumn.

\newlength{\paragraphscolwidth}
\AfterCalculatingTypearea{%
\setlength{\paragraphscolwidth}{.4\textwidth}%
\addtolength{\paragraphscolwidth}{-\marginparsep}%
}
\recalctypearea
\DeclareNewNoteColumn[%
position=\oddsidemargin+1in
+.7\textwidth
+\marginparsep,
width=\paragraphscolwidth,
font=\footnotesize
]{paragraphs}

\usepackage{environ}
\makeatletter
\NewEnviron{margintable}{%
  \expandafter\@margintable\expandafter{\BODY}%
}
\newcommand*\@margintable[1]{%
  \global\let\labeltoset\@empty
  \@tempcnta\value{table}%
  \begin{lrbox}{\@tempboxa}
    \begin{minipage}{\paragraphscolwidth}
      \def\label##1{%
        \xdef\labeltoset{%
          \labeltoset
          \noexpand\protected@write\noexpand\@auxout{}{%
            \noexpand\string\noexpand\newlabel{##1}{{\@currentlabel}{\thepage}}}%
        }%
      }%
      \def\@captype{table}%
      #1%
    \end{minipage}
  \end{lrbox}%
  \setcounter{table}{\@tempcnta}%
  \makenote[paragraphs]{%
    \protect\begin{nonfloattable}\detokenize{#1}\protect\end{nonfloattable}
  }%
  \labeltoset
}
\newenvironment{nonfloattable}{%
  \par\noindent\begin{minipage}{\linewidth}
    \def\@captype{table}%
}{%
  \end{minipage}\par
}

%% Delete all sidenotes:
%\renewcommand{\sidenote}[1]{\relax}

\begin{document}
\begin{addmargin}[0pt]{.3\textwidth}
  This is the text with a \sidenote{See here.\blindtext}.
  \blindtext


  And here we have a second paragraph and a second
  sidenote\sidenote{\blindtext}.
  \blindtext

  And this is the big hit: We can have sidenotes which include
  pagebreaks!\sidenote{Proof of concept: \blindtext{}}


  \syncwithnotecolumns[paragraphs]

      And now we somewhere have a table:
  \begin{table}[b]
    \centering
    \begin{tabular}{ll}
      Proof\sidenote{From inside the float} & of concept\\
    \end{tabular}
    \caption{This is a table}
    \label{tab:table}
  \end{table}

Besides that, we even can have tabulars in the margin\sidenote{%
  Tabular in the margin:

  \protect\begin{tabular}{|l|l|}\protect\hline
    a& b\\\protect\hline
    a& b\\\protect\hline
    a& b\\\protect\hline
  \protect\end{tabular}
}, but they have
to be narrow and well protected.

\begin{margintable}
  \centering
  \begin{tabular}{|l|l|}\hline
    a& b\\\hline
    a& b\\\hline
    a& b\\\hline
  \end{tabular}
  \caption{This is a second table}%
  \label{tab:secondtable}
\end{margintable}

See also table~\ref{tab:secondtable}.

\end{addmargin}

\listoftables

\end{document}

But note, there is still a problem: The page number of the label will be wrong if the note moves to another page.


Update: From scrlayer-notecolumn 0.1.2583 of KOMA-Script 3.23.2583 \label in notes does work as expected. And with the new \makenote* you do not need all these \protect any longer. So the following does work:

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{scrlayer-scrpage, scrlayer-notecolumn, lmodern, blindtext,
ragged2e}

%% step 1: counter
\newcounter{snmark}
\setcounter{snmark}{0}


%% step 2: hanging sidenotes, definition from tugboat
\makeatletter
\newcommand*{\hangfrom}[1]{%
  \setbox\@tempboxa\hbox{{#1}}%
  \hangindent \wd\@tempboxa
  \noindent\box\@tempboxa}
\makeatletter

%% step 3: define sidenote marks in the text
\newcommand{\makesidenotemark}{%
  \textsuperscript{\thesnmark}%
}%


%% step 4: and now the definition of sidenotes
\newcommand{\sidenote}[1]{%
  \refstepcounter{snmark}% Zähler erhöhen
  \makesidenotemark{}% Nummer im Text setzen.
  \makenote[paragraphs]{%
    \hangfrom{%
      \makebox[1em][l]{%
        \thesnmark}%
    }%
    \protect\RaggedRight\detokenize{#1}}% Text setzen im Rand
}


%% this is, except for the values (».7«) from scrguide.pdf to define
%% the notecolumn.

\newlength{\paragraphscolwidth}
\AfterCalculatingTypearea{%
\setlength{\paragraphscolwidth}{.4\textwidth}%
\addtolength{\paragraphscolwidth}{-\marginparsep}%
}
\recalctypearea
\DeclareNewNoteColumn[%
position=\oddsidemargin+1in
+.7\textwidth
+\marginparsep,
width=\paragraphscolwidth,
font=\footnotesize
]{paragraphs}

\usepackage{environ}
\makeatletter
\NewEnviron{margintable}{%
  \expandafter\@margintable\expandafter{\BODY}%
}
\newcommand*\@margintable[1]{%
  \makenote*[paragraphs]{%
    \begin{nonfloattable}#1\end{nonfloattable}%
  }%
}
\newenvironment{nonfloattable}{%
  \par\noindent\begin{minipage}{\linewidth}
    \def\@captype{table}%
}{%
  \end{minipage}\par
}
\usepackage{makeidx}

%% Delete all sidenotes:
%\renewcommand{\sidenote}[1]{\relax}

\begin{document}
\begin{addmargin}[0pt]{.3\textwidth}
  This is the text with a sidenote\sidenote{See here.\blindtext}.
  \blindtext


  And here we have a second paragraph and a second
  sidenote\sidenote{\blindtext}.
  \blindtext

  And this is the big hit: We can have sidenotes which include
  pagebreaks!\sidenote{Proof of concept: \blindtext{}}


  \syncwithnotecolumns[paragraphs]

      And now we somewhere have a table:
  \begin{table}[b]
    \centering
    \begin{tabular}{ll}
      Proof\sidenote{From inside the float} & of concept\\
    \end{tabular}
    \caption{This is a table}
    \label{tab:table}
  \end{table}

Besides that, we even can have tabulars in the margin\sidenote{%
  Tabular in the margin:

  \begin{tabular}{|l|l|}\hline
    a& b\\\hline
    a& b\\\hline
    a& b\\\hline
  \end{tabular}%
}, but they have
to be narrow and well protected.

\begin{margintable}
  \centering
  \begin{tabular}{|l|l|}\hline
    a& b\\\hline
    a& b\\\hline
    a& b\\\hline
  \end{tabular}
  \caption{This is a second table}%
  \label{tab:secondtable}
\end{margintable}

See also table~\ref{tab:secondtable}.
\listoftables

\end{addmargin}


\end{document}

For \sidenote you cannot use \makenote*, because \thesnmark needs to be expanded immediately. But you can use the \detokenize trick of \makenote* yourself as shown in the example above.

BTW: In the code above I have fixed several space mistakes.