diff --git a/web/SitePreview.tsx b/web/SitePreview.tsx index 336b1be..08c91ad 100644 --- a/web/SitePreview.tsx +++ b/web/SitePreview.tsx @@ -271,22 +271,36 @@ export const SitePreview = ({ measure guides running down through it. Nothing was broken; the frame was simply taller than the document, and an iframe has no `height: fit-content`. - ── The WRAPPER, not the body ── + ── The WRAPPER, with its minimum height taken off ── - The site's `` is `min-h-screen`, so its height is the FRAME's height and measuring it would - ask the frame how tall the frame is. Its one child is the page — header, main, footer — and that is - a real content height. It stopped being `min-h-dvh` on the same day this changed, for the same - reason: the stretch belonged to nothing anybody could see or set. + The site's `` is `min-h-screen` and the page shell inside it is `min-h-dvh`, so measuring + either asks the frame how tall the frame is and the answer is whatever it already was. Both are + right on a real page — a short one should put its footer at the bottom of the window — and both + make this circular. + + So the minimum is neutralised in the frame before measuring, by a stylesheet this injects. What is + left is the height of what is actually on the page, which is what the panel should be. + + The cost, stated: the preview does not show the footer pushed to the bottom of a window, because it + is not a window. It shows the page ending where the page ends. */ const [contentHeight, setContentHeight] = useState(0); useEffect(() => { if (!loaded) return; const frameDocument = frame.current?.contentDocument; - const page = frameDocument?.body.firstElementChild as HTMLElement | null; + const page = frameDocument?.querySelector('[data-page-shell]') ?? (frameDocument?.body.firstElementChild as HTMLElement | null); const view = frameDocument?.defaultView; if (!page || !view) return; + /* + Injected rather than set inline: `min-h-dvh` is a class, and an inline `min-height` would have to + win against it by specificity. A stylesheet of our own, last in the document, does. + */ + const relax = frameDocument!.createElement('style'); + relax.textContent = '[data-page-shell]{min-height:0!important}body{min-height:0!important}'; + frameDocument!.head.append(relax); + const measure = () => setContentHeight(Math.ceil(page.getBoundingClientRect().height)); measure(); @@ -299,7 +313,10 @@ export const SitePreview = ({ */ const observer = new view.ResizeObserver(measure); observer.observe(page); - return () => observer.disconnect(); + return () => { + observer.disconnect(); + relax.remove(); + }; }, [loaded]); /*