Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to position sidenotes with CSS

What I want

Sidenotes. The foremost concern is, of course, placing them at a height relative to that of the text referencing them. I can do it with JavaScript, looking at the offsetTop property of the note reference, but then I would have to handle viewport resizes and zooming as well, whereas a CSS solution would leave that to the browser. A CSS solution is thus preferable.

Background and motivation

This is part of the responsive design of a blog. Notes shall be displayed as sidenotes if there is enough room for them in the margins; otherwise, they shall appear as footnotes. This post explains it in more detail. Keep in mind that, past a certain width, we'll have margins anyway, since text lines cannot exceed a certain length if they are to remain readable, so we could as well employ that otherwise unused space. Tufte is a well-known proponent of this solution.

What I have tried

So far I have tried two approaches. Both of them use relative positioning on the marker (a <sup>) so as to be able to position the note (a <span>) with a top offset relative to that of the referencing text.


My first try employs absolute positioning:

article {
   width: 50%;
   margin-left: auto;
   margin-right: auto;
}

sup {
   /* Needed to position sidenotes */
   position: relative;
}

.sidenote {
   width: 20%;
   position: absolute;
   
   /* BTW: This should be proportional to the note's height,
      so as to make its vertical center align with the text
      referencing it */
   top: -100%;
}

/* How could I set the notes' horizontal position relative to the margin or to an element other than the enclosing <sup>? */
.sidenote.l {
   right: 0;
}
.sidenote.r {
   left: 15vw;
}
<article>
   <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat<sup>1<span class="sidenote r">Several variations of this sentence are known.</span></sup>. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
   </p>
</article>

The problem here is horizontal positioning. Since our reference is the <sup>, it becomes tricky to set the sidenote near the margin. It might be doable with JavaScript, but then I would have to update the offset every time the viewport was resized. Not looking forward to it.

This post suggests a similar approach, but doesn't show which parent should be set as reference with relative positioning. If it's the <p>, the problem arises that we can only have one note on each side per paragraph, which is a limitation I would rather avoid.


My second try revolves around CSS grid:

article {
   display: grid;
   grid-template-columns: 15% auto 15%;
}

p {
   grid-column: 2;
}

sup {
   position: relative;
}

.sidenote.l {
   grid-column: 1;
}

.sidenote.r {
   grid-column: 3;
}
<article>
   <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat<sup>1<span class="sidenote r">Several variations of this sentence are known.</span></sup>. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
   </p>
</article>

However, it seems as though it weren't possible to put a child (the <span>) in a different grid column than the one its parent (the <sup>) belongs to.

like image 841
Kalrish Avatar asked Jan 29 '18 15:01

Kalrish


2 Answers

You can do that using float: right; on the sidenote element (which aligns it right) and a negative margin-right value which is equal to or more than the width of the sidenote itself and will move the sidenote element out of the main text container. The floating also makes sure it's always at the height of the related text.

(the other position settings are unnessessary and can be erased in this case)

ADDITION AFTER COMMENT: To move it upwards in order to center it vertically, you can use position: relative; and transform: translateY(-50%); on it, which should move it up half of its own height. However, for some reason that moves it up too muc, so I changed it to 30% in my snippet - try to find a value that suits you...

(However, this will probably cause problems when it's at the top of a column/page)

article {
  width: 50%;
  margin-left: auto;
  margin-right: auto;
}
.sidenote {
  float: right;
  width: 20%;
  margin-right: -21%;
  position: relative;
  transform: translateY(-30%);
}
<article>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat<sup>1<span class="sidenote">Several variations of this sentence are known.</span></sup>.
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
</article>
like image 133
Johannes Avatar answered Nov 13 '22 15:11

Johannes


You could position the sidenotes using margin instead of absolute.

Basic example...

fiddle

article {
  width: 50%;
  margin-left: auto;
  margin-right: auto;
}

.sidenote {
  width: 20%;
  float: right;
  clear: right;
  margin-right: -33%;
}
<article>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat<sup>1</sup><span class="sidenote">Several variations of this sentence are known.</span>.
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
</article>
like image 24
sol Avatar answered Nov 13 '22 13:11

sol