fix: sidenote positioning uses offsetTop, not getBoundingClientRect

getBoundingClientRect() is viewport-relative; subtracting parent.top was
unreliable depending on scroll position at call time. Switch to
h.offsetTop, which gives distance from .sidenote-host to .e-content's
padding edge directly (because .e-content is position:relative = offsetParent).
Also replace DOMContentLoaded listener (already fired at script injection time)
with requestAnimationFrame for immediate post-paint positioning.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
svemagie
2026-03-27 18:44:42 +01:00
parent 0db48ac6fa
commit 8f28ee43ec
+4 -1
View File
@@ -590,7 +590,10 @@ export default function (eleventyConfig) {
// 5. Inject positioning script before </body>
// Sets each sidenote's top relative to .e-content, with overlap prevention.
const posScript = `(function(){function p(){if(window.innerWidth<1440)return;var a=document.querySelector('article.has-sidenotes');if(!a)return;var e=a.querySelector('.e-content');if(!e)return;var cr=e.getBoundingClientRect();var lb=0;a.querySelectorAll('.sidenote').forEach(function(s){var h=s.parentElement;var hr=h.getBoundingClientRect();var t=Math.max(hr.top-cr.top,lb);s.style.top=t+'px';lb=t+s.offsetHeight+8;});}document.addEventListener('DOMContentLoaded',p);window.addEventListener('load',p);window.addEventListener('resize',p);})();`;
// offsetTop is measured from .e-content's padding edge because .e-content
// is position:relative — its offsetParent. Script is injected at end of
// <body> so DOM is ready; call p() immediately (rAF for paint stability).
const posScript = `(function(){function p(){if(window.innerWidth<1440)return;var a=document.querySelector('article.has-sidenotes');if(!a)return;var e=a.querySelector('.e-content');if(!e)return;var lb=0;a.querySelectorAll('.sidenote').forEach(function(s){var h=s.parentElement;var t=Math.max(h.offsetTop,lb);s.style.top=t+'px';lb=t+s.offsetHeight+8;});}requestAnimationFrame(p);window.addEventListener('load',p);window.addEventListener('resize',p);})();`;
tree.walk(node => {
if (node.tag === "body") {
node.content = node.content || [];