diff --git a/docs/main.js b/docs/main.js index ef1899e44..12b211351 100644 --- a/docs/main.js +++ b/docs/main.js @@ -209,6 +209,27 @@ class HeadingObserver { this.manageHistoryEntries = manageHistoryEntries; this.visibleOnly = visibleOnly; + // While we're here, spy on the page header height. The sidebar is + // `position: sticky` but requires `--page-header-height` to be a specific + // pixel value. Since `--page-header-height` can sometimes be `auto`, this + // doesn't work. + // + // The fix is to let `--page-header-height` be the source of truth for, uh, + // the page header's height… but derive a different property from its + // actual height measurement in pixels. That way we can do arithmetic + // against it in CSS elsewhere — like when determining the correct + // top-offset for a `position: sticky` sidebar. + this.header = document.querySelector('header'); + this.resizeObserver = new ResizeObserver((entries) => { + let [entry] = entries; + let rect = entry.contentRect; + document.documentElement.style.setProperty('--actual-page-header-height', `${rect.height}px`); + }); + + if (this.header) { + this.resizeObserver.observe(this.header); + } + let threshold = []; for (let i = 0; i <= 20; i++) { threshold.push(i * 0.05); diff --git a/less/general.less b/less/general.less index 25c12184e..f59b00a81 100644 --- a/less/general.less +++ b/less/general.less @@ -11,3 +11,16 @@ text-align: center; width: 20px; } + +// TODO: This should be universal. +@media (min-width: @bp-larger-than-tablet) { + .sidebar { + // `--actual-page-header-height` is set through JavaScript and is + // guaranteed to be a concrete value. `--page-header-height` only + // guarantees it's a valid `height` value — hence could be `auto`. + // + // So we prefer the first and reluctantly fall back to the second. + top: calc(var(--actual-page-header-height, var(--page-header-height, 0)) + 1.5rem); + max-height: calc(95vh - var(--actual-page-header-height, var(--page-header-height, 0))); + } +}