How to position sidenotes with CSS
Asked Answered
T

2

9

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.

Theroid answered 29/1, 2018 at 15:4 Comment(10)
I believe you're thinking too much about the technical part and not enough about usability. You have some extra content you want to present to users, besides the text itself, which should otherwise make sense without the extra-content. If the user shows interest in the extra content, you want to give them the ability to focus on it, read it and return to main content. The practical way to do it cross-browser/cross-device are tooltips or popovers. Mark their presence boldly and display them over the text. Talk to a designer about how to keep it appealing on any device.Araucanian
@AndreiGheorghiu How would you handle the sidenotes if a user decides to print the article? tooltips etc won't workApartment
@Apartment By asking this question you are defending the choice of bringing a print technique into digital. Handle print with print techniques and digital with digital techniques. The need of the two to match pixel perfect is null. The need of them to function on any device with ease and intuitively, while still looking attractive, on the other hand, is vital for the success of whatever you're coding. Look for simple solutions that make sense. When needing to take this type of decisions I usually talk to non-technical people asking what would make sense to them.Araucanian
@AndreiGheorghiu Thanks that makes sense. But I'm not sure sidenotes are typically something you'd 'click' or 'hover over' to reveal.. usually (I'm thinking book) they're present alongside text.Apartment
@AndreiGheorghiu This is a responsive design: notes are displayed as footnotes when printing and if the viewport is not wide enough; only if there's room for them are they displayed on the margins. Keep in mind that text lines cannot span the entire width of the viewport, because that makes text less readable, so on desktops we're gonna have blank margins anyway. Sidenotes just take that otherwise unused space. Tufte is usually cited as the reference on this matter. Tooltips and popovers might be an option as well, but they are not to my taste.Theroid
If you have responsiveness covered you should add this detail in the question. Also note current answers only give you solutions for one side-note/row and you probably look for solutions for multiple side-notes per 1-2 rows. If you don't ask the right question, you're not going to get the right answer.Araucanian
@AndreiGheorghiu Responsiveness is not really relevant. Sidenotes are just a part of its implementation, and omitting the bigger picture makes them easier to achieve. If I get this part working, it'll be straightforward to plug the solution into the decision-making code. On the other hand, could you explain what you mean with rows?Theroid
In print it's common to have more than one note in the same place. <sup>1</sup><sup>2</sup>. Or maybe at a few words distance. Is the answer you are looking for supposed to cover this case?Araucanian
@AndreiGheorghiu Ideally, yes. But I supposed this can't be implemented in pure CSS and hoped either not to ever find myself in such a situation or to be able to handle it building upon whatever solution I found.Theroid
Just to counter some of the “it’s a bad idea anyway” vibe, here: I’m a designer and I believe sidenotes are not only appropriate for use on wide web layouts, but their benefits over footnotes are even stronger in this context than on the printed page. Also, I hate CSS for making them so difficult.Glove
C
7

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>
Consalve answered 29/1, 2018 at 15:58 Comment(2)
Thank you. Would it be possible to move the sidenote upwards, to align its vertical center with the text referencing it?Theroid
See the addition to my answer and to the snippetConsalve
A
2

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>
Apartment answered 29/1, 2018 at 15:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.