Here’s how I recently implemented sidenotes, following the original Tufte-CSS markup approach which I liked because it’s pretty clever and doesn’t require javascript.
I only did “sidenotes” (numbered footnotes), but “marginnotes” (floating content without numbers) should be pretty straight forward with the same approach.
First, I added a structure field sidenotes
to my article blueprint, below the main blocks
field:
sidenotes:
type: structure
label: Sidenotes
fields:
text:
label: Text
type: writer
Then created a plugin for the new Kirbytag (sn:<number>)
:
// site/plugins/tufte/index.php
Kirby::plugin('bruno/tufte', [
'tags' => [
'sn' => [
'html' => function($tag) {
$sidenotes = $tag->parent()->sidenotes()->toStructure();
$return = '';
if ($sidenotes
&& $note = $sidenotes->nth($tag->value() - 1)) {
$text = $note->text()->kirbyText();
$text = preg_replace( '/^<[^>]+>|<\/[^>]+>$/', '', $text);
$return = '<label for="sn-' . $tag->value . '" class="sidenote-number"></label><input type="checkbox" id="sn-' . $tag->value . '" class="margin-toggle"/><span class="sidenote">' . $text . '</span>';
$return = $return;
}
return $return;
}
],
],
],
It’s ugly, but it works and produces the following markup:
<label for="sn-1" class="sidenote-number"></label>
<input type="checkbox" id="sn-1" class="margin-toggle">
<span class="sidenote"> {{ SIDENOTE TEXT }} </span>
I included the original Tufte.css file, but added some attributes to make it more customizable – most notably the css variables in root which allow easily tailoring the layout:
/* assets/css/tufte.css */
:root {
--tufte-width: 350px;
--tufte-distance: 50px;
counter-reset: sidenote-counter;
}
.sidenote {
float: right;
clear: right;
width: var(--tufte-width);
margin-right: calc(var(--tufte-width) * -1);
margin-bottom: 1rem;
padding-left: var(--tufte-distance);
vertical-align: baseline;
position: relative;
}
.sidenote-number {
counter-increment: sidenote-counter;
}
.sidenote-number:after,
.sidenote:before {
position: relative;
vertical-align: baseline;
}
.sidenote-number:after {
content: counter(sidenote-counter);
font-size: .8rem;
top: -0.5rem;
left: 0.1rem;
}
.sidenote:before {
content: counter(sidenote-counter) " ";
font-size: .7rem;
top: -0.5rem;
}
input.margin-toggle {
display: none;
}
label.sidenote-number {
display: inline;
}
label.margin-toggle:not(.sidenote-number) {
display: none;
}
@media (max-width: 800px) {
label.sidenote-number {
display: inline;
cursor: pointer;
}
.sidenote {
display: none;
}
label.margin-toggle:not(.sidenote-number) {
display: inline;
font-size: 1.3rem;
line-height: 1rem;
}
.margin-toggle:checked + .sidenote {
display: block;
float: left;
left: 1rem;
clear: both;
width: 95%;
margin: 1rem 2.5%;
vertical-align: baseline;
position: relative;
}
}
Result:
Notes/Side effects:
- It’s not semantic.
- If you copy&paste text with this markup, it will always include the footnotes content mashed in right where they are registered with the
(sn:)
tag.
- It’s (probably) not very accessible. Some javascript and aria-attributes should in fact be applied.