Side notes with references to text
See original GitHub issueDescription
Margin / sidenote content is an important part of Jupyter Book, as Tufte CSS recommends (see “Sidenotes: Footnotes and Marginal Notes”). However, the functionality is currently a bit simple, and we could improve this considerably.
This theme currently implements “margin notes” with one pattern:
```{margin}
Margin content
```
This is block-level content that behaves like an admonition, and adds the margin
class, which causes it to pop out to the margin.
However, there are a few downsides to this:
- It doesn’t follow the suggested structure that Tufte recommends for HTML sidenotes/margin notes
- As a result it is displayed automatically on more narrow screens, whereas Tufte recommends having it hidden by default with a click to show
- We do not implement “numbered” sidenotes, only un-numbered ones.
- We only have a block-level directive, not an inline role
- (optionally) all of these are defined in the
sphinx-book-theme
, but ideally these could be an independent sphinx extension so that other themes could implement support for this as well
We could address these limitations by defining a more complete set of roles/directives that address the use-cases described in Tufte.
Implementation guide
Role/directive naming + structure
Tufte uses these names for things:
- marginnotes are un-numbered notes in the margin, with no reference point in the text.
- sidenotes are numbered notes in the margin, with a corresponding number in the text.
So I think it makes sense for marginnotes
to have both an inline and a block implementation, whereas sidenotes
only need an inline implementation since they need some text to refer to anyway.
There’s a similar implementation of this in the Jekyll Tufte Theme. In the margin notes section, they show the liquid template that is used to inject this content:
{% sidenote 'sn-id-whatever' 'This is a sidenote and *displays a superscript*'%}
{% marginnote 'mn-id-whatever' 'This is a margin note *without* a superscript' %}
We could accomplish something similar with
block-level directives
```{marginnote} Title
Content
```
inline-level roles
Some text and {marginnote}`a margin note`.
Some text and {sidenote}`a side note`.
We could auto-generate the id
for each, so that users don’t need to manually provide it. In the future we could explore enabling user-provided id
via a pattern like
```{margin} Title
:label: my-label
Content
```
Some text and {sidenote}`"my-label" "a side note"`.
HTML / CSS implementation
Here’s what Tufte CSS recommends for the in-line content:
Margin notes do not have numbered labels and so it just a matter of getting the right HTML/CSS behavior:
<label for="mn-demo" class="margin-toggle">⊕</label>
<input type="checkbox" id="mn-demo" class="margin-toggle"/>
<span class="marginnote">
This is a margin note. Notice there isn’t a number preceding the note.
</span>
We might explore doing this with an <aside>
element since that is semantically closer to what this is.
Side Notes have a reference number, so are a bit more complicated. They add on an extra bit of HTML to include the first label.
<label for="sn-demo"
class="margin-toggle sidenote-number">
</label>
<input type="checkbox"
id="sn-demo"
class="margin-toggle"/>
If we don’t require clickable links between the label and the sidenote, then we should be able to relatively easy get this to work with CSS counters and the counter-increment
rule.
Basically this means some combination of:
-
For the first instance of sidenote, initialize it with a CSS rule:
counter-reset: sidenote-conuter;
-
Whenever we want the label to show up, use an
::after
or::before
and include something like the following:.sidenote::before { content: counter(sidenote-counter) " "; }
-
When in subsequent sidenote instances, use a CSS rule to increment the counter:
::before { counter-increment: section; /* Increment the value of section counter by 1 */ }
See how the Tufte HTML is structured for more reference.
Updates and tasks
Issue Analytics
- State:
- Created 3 years ago
- Reactions:30
- Comments:20 (19 by maintainers)
Top GitHub Comments
I think that ultimately this does make sense as its own extension, so that the directives, roles, and subsequent html / latex behavior could be standardized. Then themes could define their own CSS to make the html behave as they wished. But I agree that it would be easiest to make quick progress by piggy backing on the work that is already in the book theme. I’m happy to review PRs that give this a shot in either location!
That sounds good to me - it would be great to see some prototypes of margin/sidenote directives.
I agree with @AakashGfude that we don’t want to be too opinionated in the implementation. I think we should use the semantics and structure Tufte though, since it’s a known structure by a respected authority. Maybe we should just pick some simple and clean UI that a theme developer could fancy up if they wanted to with their own CSS.
As far as being its own extension or not, I don’t have strong opinions. I guess it’s a question if whether we think of these two features as inherently linked (or, if they’re just similar enough that it’s worth combining just for simplicity).
FYI here are the relevant bits of code:
Sidebar
directive to add a margin-specific class. So we might want to change this if we wanted the structure to be differentThere might be parts about the Sphinx Book Theme that we don’t want to copy over - e.g., we probably don’t want to assume whether a margin is even present, since some themes don’t explicitly make whitespace for it. But I think we’ll start figuring it out once we’ve got some code to work with.