#301: sort the reflow report so the culprit cannot be buried

CI still reports 737 while the local stack is now clean, and the box list
was capped at 15 entries — all of them nav links clipped by their own
scroller. Whatever pushes the page in CI sits past that cap.

The list is now sorted by reach, marks each entry as either clipped by a
fitting scroller or actually pushing the page, and shows 40.
This commit is contained in:
Claude Opus 5 2026-08-01 11:15:36 +02:00 committed by Claude Fable 5
parent b65339ae13
commit 2422f3a28f

View File

@ -141,20 +141,36 @@ async function expectNoHorizontalScroll(page: Page, label: string): Promise<void
}
}
// Raw: every box reaching past the viewport, no filtering at all.
const past: string[] = [];
for (const el of Array.from(document.querySelectorAll('body *'))) {
const rect = el.getBoundingClientRect();
if (rect.width > 0 && rect.right > limit + 1) {
past.push(`${describe(el)} right=${Math.round(rect.right)} w=${Math.round(rect.width)}`);
/** Content inside a scroll container may exceed the viewport that is
* the remedy. But only when the CONTAINER fits: a scroller that is
* itself too wide still pushes the page. */
const insideFittingScroller = (el: Element): boolean => {
for (let node = el.parentElement; node && node !== doc; node = node.parentElement) {
const ox = getComputedStyle(node).overflowX;
if (ox === 'auto' || ox === 'scroll' || ox === 'hidden') {
return node.getBoundingClientRect().right <= limit + 1;
}
}
return false;
};
// Widest reach first, so a long tail of clipped children cannot bury the
// one box that actually pushes the page.
const past = Array.from(document.querySelectorAll('body *'))
.map((el) => ({ el, rect: el.getBoundingClientRect() }))
.filter(({ rect }) => rect.width > 0 && rect.right > limit + 1)
.sort((a, b) => b.rect.right - a.rect.right)
.map(
({ el, rect }) =>
`${describe(el)} right=${Math.round(rect.right)} w=${Math.round(rect.width)}` +
`${insideFittingScroller(el) ? ' [in fitting scroller]' : ' <-- pushes page'}`,
);
return {
overflowBy: doc.scrollWidth - limit,
viewport: `html client=${limit} scroll=${doc.scrollWidth} | body client=${document.body.clientWidth} scroll=${document.body.scrollWidth} rect=${Math.round(document.body.getBoundingClientRect().width)}`,
overflowing: overflowing.slice(0, 15),
past: past.slice(0, 15),
past: past.slice(0, 40),
};
});
const diagnosis = [