diff --git a/src/content/posts/how-i-made-my-own-songs-with-suno-ai.md b/src/content/posts/how-i-made-my-own-songs-with-suno-ai.md index 248fc7c..ed54315 100644 --- a/src/content/posts/how-i-made-my-own-songs-with-suno-ai.md +++ b/src/content/posts/how-i-made-my-own-songs-with-suno-ai.md @@ -88,7 +88,7 @@ Publitio) and embedded with plain HTML5 audio. Press play: @@ -297,8 +297,11 @@ document.querySelectorAll('audio[data-lrc]').forEach((audio) => { if (cur >= 0) { const p = box.children[cur]; p.classList.add('on'); - // scroll the lyric box only (scrollIntoView would drag the whole page) - box.scrollTo({ top: p.offsetTop - box.clientHeight / 2 + p.offsetHeight / 2, behavior: 'smooth' }); + // centre the active line inside the box. Use rect deltas, NOT offsetTop: + // offsetTop is measured from the nearest *positioned* ancestor, so without + // position:relative on the box it is huge and scrollTop clamps to the bottom. + const br = box.getBoundingClientRect(), pr = p.getBoundingClientRect(); + box.scrollTop += (pr.top - br.top) - (box.clientHeight - pr.height) / 2; } else { box.scrollTop = 0; // back to the top before the first line } diff --git a/src/content/posts/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md b/src/content/posts/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md index 283025f..cc4b1e4 100644 --- a/src/content/posts/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md +++ b/src/content/posts/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md @@ -227,7 +227,7 @@ against the written lyrics, since the model emits no timestamps. @@ -961,8 +961,11 @@ document.querySelectorAll('audio[data-lrc]').forEach((audio) => { if (cur >= 0) { const p = box.children[cur]; p.classList.add('on'); - // scroll the lyric box only (scrollIntoView would drag the whole page) - box.scrollTo({ top: p.offsetTop - box.clientHeight / 2 + p.offsetHeight / 2, behavior: 'smooth' }); + // centre the active line inside the box. Use rect deltas, NOT offsetTop: + // offsetTop is measured from the nearest *positioned* ancestor, so without + // position:relative on the box it is huge and scrollTop clamps to the bottom. + const br = box.getBoundingClientRect(), pr = p.getBoundingClientRect(); + box.scrollTop += (pr.top - br.top) - (box.clientHeight - pr.height) / 2; } else { box.scrollTop = 0; // back to the top before the first line } diff --git a/src/content/posts/zh/how-i-made-my-own-songs-with-suno-ai.md b/src/content/posts/zh/how-i-made-my-own-songs-with-suno-ai.md index 2d8e987..b43e670 100644 --- a/src/content/posts/zh/how-i-made-my-own-songs-with-suno-ai.md +++ b/src/content/posts/zh/how-i-made-my-own-songs-with-suno-ai.md @@ -74,7 +74,7 @@ v6 家族新增的控制功能,直接改变了我做事的方式: @@ -276,8 +276,11 @@ document.querySelectorAll('audio[data-lrc]').forEach((audio) => { if (cur >= 0) { const p = box.children[cur]; p.classList.add('on'); - // scroll the lyric box only (scrollIntoView would drag the whole page) - box.scrollTo({ top: p.offsetTop - box.clientHeight / 2 + p.offsetHeight / 2, behavior: 'smooth' }); + // centre the active line inside the box. Use rect deltas, NOT offsetTop: + // offsetTop is measured from the nearest *positioned* ancestor, so without + // position:relative on the box it is huge and scrollTop clamps to the bottom. + const br = box.getBoundingClientRect(), pr = p.getBoundingClientRect(); + box.scrollTop += (pr.top - br.top) - (box.clientHeight - pr.height) / 2; } else { box.scrollTop = 0; // back to the top before the first line } diff --git a/src/content/posts/zh/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md b/src/content/posts/zh/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md index 8367626..1ab694f 100644 --- a/src/content/posts/zh/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md +++ b/src/content/posts/zh/yue2-on-a-12gb-gpu-songs-that-lost-their-endings.md @@ -172,7 +172,7 @@ clean = "\n".join(l for l in raw.split("\n") @@ -906,8 +906,11 @@ document.querySelectorAll('audio[data-lrc]').forEach((audio) => { if (cur >= 0) { const p = box.children[cur]; p.classList.add('on'); - // scroll the lyric box only (scrollIntoView would drag the whole page) - box.scrollTo({ top: p.offsetTop - box.clientHeight / 2 + p.offsetHeight / 2, behavior: 'smooth' }); + // centre the active line inside the box. Use rect deltas, NOT offsetTop: + // offsetTop is measured from the nearest *positioned* ancestor, so without + // position:relative on the box it is huge and scrollTop clamps to the bottom. + const br = box.getBoundingClientRect(), pr = p.getBoundingClientRect(); + box.scrollTop += (pr.top - br.top) - (box.clientHeight - pr.height) / 2; } else { box.scrollTop = 0; // back to the top before the first line }