diff --git a/mkdocs_doubleslash_theme/assets/javascripts/toc-collapse-toggle.js b/mkdocs_doubleslash_theme/assets/javascripts/toc-collapse-toggle.js index e76873f..cfc3bfe 100644 --- a/mkdocs_doubleslash_theme/assets/javascripts/toc-collapse-toggle.js +++ b/mkdocs_doubleslash_theme/assets/javascripts/toc-collapse-toggle.js @@ -158,12 +158,18 @@ } var width = wrapper.getBoundingClientRect().width; - // Extra 20px breathing room from the grid edge, but only when parked - // there in the collapsed state — flush against the ToC divider - // otherwise. Never closer than 20px to the real viewport edge either, - // or the wrapper ends up pinned to it on viewports with little margin. - var gap = collapsed ? 20 : 0; - var right = Math.max(20, window.innerWidth - anchor.getBoundingClientRect().right - width - gap); + // Extra 20px breathing room from the grid edge when parked there in + // the collapsed state; a smaller 8px gap otherwise so the button + // doesn't sit flush against the sidebar's scrollbar. Never closer + // than 20px to the real viewport edge either, or the wrapper ends up + // pinned to it on viewports with little margin. + var gap = collapsed ? 20 : 18; + // position:fixed's `right` is relative to the document's clientWidth + // (viewport minus scrollbar), not window.innerWidth (which includes + // it) — using innerWidth here pushed the button left by the + // scrollbar's own width, into the sidebar. + var viewportWidth = document.documentElement.clientWidth; + var right = Math.max(20, viewportWidth - anchor.getBoundingClientRect().right - width - gap); wrapper.style.right = right + "px"; } diff --git a/mkdocs_doubleslash_theme/assets/stylesheets/mkdocs-doubleslash-theme.css b/mkdocs_doubleslash_theme/assets/stylesheets/mkdocs-doubleslash-theme.css index 0c7e0d9..72481d0 100644 --- a/mkdocs_doubleslash_theme/assets/stylesheets/mkdocs-doubleslash-theme.css +++ b/mkdocs_doubleslash_theme/assets/stylesheets/mkdocs-doubleslash-theme.css @@ -31,6 +31,12 @@ --ds-motion-duration: 0.3s; --ds-motion-transition: var(--ds-motion-duration) ease all; --ds-wide-max-width: min(1800px, 100% - 4rem); + /* Separate from --ds-wide-max-width (used for the actual reading column + fill-width): this is only for .md-main__inner/.md-grid's own margin, + where 8rem (4rem per side) leaves enough room for the sidebar-collapse + toggle buttons (43px + 20px gap ≈ 63px each) to sit outside it without + drifting off-screen at narrower viewports. */ + --ds-grid-max-width: min(1800px, 100% - 8rem); /* Typography tokens — source: frontend/DESIGN.md (living-styleguide, ref=main) */ --ds-typography-body-website-font-size: 18px; @@ -63,6 +69,14 @@ --ds-typography-heading-h6-margin-bottom: 12px; } +/* Material scales the root font-size in three hard jumps (125% / 137.5% / + 150% at 100em / 125em) — every rem-based size and spacing on the page + snaps at those breakpoints. clamp() scales it continuously instead: 20px + up to ~1600px, 24px from ~2560px, linear in between. */ +html { + font-size: clamp(20px, 16px + 0.3125vw, 24px); +} + [data-md-color-scheme="default"] { --md-primary-fg-color: var(--ds-color-on-primary); --md-primary-bg-color: var(--ds-color-primary); @@ -244,6 +258,15 @@ sidebar divider instead of floating centered in the available space. */ .md-content__inner { max-width: 90ch; + /* Capped at the column's own available width too: .md-content__inner + isn't itself a flex item — it's a plain block inside the + .md-content column that the sidebars already shrank — so an + unqualified 70ch floor ignores that shrunk width and overflows + into the ToC/nav sidebar whenever both are open on a narrower + viewport. min() keeps the floor from exceeding it; the 2.4rem + subtracted is this element's own left+right margin (1.2rem each), + which sits outside the border-box that min-width sizes. */ + min-width: min(70ch, calc(100% - 2.4rem)); transition: max-width var(--ds-motion-duration) ease; } @@ -413,16 +436,22 @@ width: 1rem; } +/* The ToC toggle is offered starting at 60em (below), narrower than the + 76.25em block below — without room here too, it has nowhere to sit but + on top of the ToC sidebar, which is flush against the viewport edge at + these widths. */ +@media screen and (min-width: 60em) { + .md-grid { + max-width: var(--ds-grid-max-width); + } +} + /* Only constrain width on wide desktop layouts (>= 76.25em) — unguarded, the "100% - 4rem" term shrinks these below their natural width on ANY viewport, adding unwanted side margins on mobile too. Content only picks up the same width as .md-grid once a sidebar is actually collapsed, so it stays aligned with the header instead of fighting the 90ch reading cap. */ @media screen and (min-width: 76.25em) { - .md-grid { - max-width: var(--ds-wide-max-width); - } - /* Once a sidebar is actually collapsed, drop the 90ch reading cap so text fills the reclaimed space instead of leaving it padded out on one side — that's the whole point of the widen toggle. Material's own @@ -733,8 +762,9 @@ } } -/* Remove the opaque background/box-shadow Material adds to the sticky ToC title */ +/* Remove Material's box-shadow on the sticky ToC title, but keep an opaque + background — otherwise scrolled-past headings show through behind it. */ .md-nav--secondary .md-nav__title { - background-color: transparent; + background-color: var(--md-default-bg-color); box-shadow: none; } \ No newline at end of file