Test layouts in real viewports
What you'll see
A responsive layout is checked by dragging the browser window narrow, or through devtools device emulation. It looks acceptable, but real phones show problems that never appeared during testing — a navigation bar that wraps onto two lines, a card grid whose right-hand column is cut off, a fixed bottom bar covering the footer.
The checks that were run each covered one width at a time, and none of them covered the whole page at that width.
What's actually happening
A resized window tests one viewport; you need all of them at once. An <iframe> establishes its own layout viewport, so media queries inside it evaluate against the frame's dimensions rather than the host window's. A grid of same-origin iframes, each sized to a real device viewport, renders every breakpoint simultaneously — one screenshot then covers the whole matrix.
Scrollable frames hide the worst bugs
A frame with a device-sized height only shows the first screenful. Sections further down are never seen unless you scroll inside each frame individually, which is slow enough that it does not get done.
Worse, horizontal overflow is silently clipped. With overflow-x: hidden on body — which most mobile-first stylesheets set — a grid column that extends past the viewport is simply cut off. Nothing scrolls, nothing errors, and the layout looks intentional until you compare it against the markup and notice a column is missing.
The grid track trap
The canonical cause of that overflow: a grid track declared 1fr resolves to minmax(auto, 1fr), and auto as a minimum means min-content. If any cell contains a word wider than the track's fair share, the track grows past the viewport instead of shrinking. Norwegian compound nouns trigger this constantly — Produksjonsplanlegging and ressursplanlegging have a min-content width wider than half a 390 px phone screen.
Breakpoint boundaries, not just devices
Testing 375 px and 1440 px says nothing about 1024 px. A desktop navigation that switches on at 992 px may not fit until ~1100 px, so iPad landscape lands in a dead zone where the full menu renders but wraps onto two lines and collides with the logo. That width is only visible if you deliberately include a frame at it.
What to do
Build the harness as a plain page
Keep the sizes in CSS via attribute selectors so the markup stays declarative and the page renders without JavaScript:
<div class="vp__shell" data-w="390" data-h="844">
<iframe src="/index2" title="390px bredde" loading="lazy"></iframe>
</div> .vp__shell[data-w="390"] { width: 390px; }
.vp__shell[data-h="844"] { height: 844px; }
.vp__shell iframe { width: 100%; height: 100%; border: 0; } If you want to retarget the harness at other pages, read a ?url= parameter from a separate script file — inline scripts are blocked by a typical script-src 'self' CSP. Validate that the value starts with a single / so the harness cannot be used to frame other sites, and leave a working src in the HTML so the page still functions if the script fails.
Include the breakpoint boundaries
Add a frame at the narrowest width you support (320 px), one at each device class, and one one pixel below each breakpoint — 991 px for a 992 px rule. That is where collapse-too-late bugs live.
Add one full-height frame
Give a final mobile-width frame a height large enough for the entire document, so the whole page lays out in one pass and you review it by scrolling the host window:
.vp__shell--tall { height: 7200px; resize: none; } This is the frame that surfaces clipped columns and unreviewed sections. It is worth the one extra page load.
Fix overflow at the track, then the word
- Declare tracks
minmax(0, 1fr)so they may shrink below min-content. - Add
overflow-wrap: break-wordto the text so it breaks rather than escaping the card. - Ensure the text actually has a width to break against. Inside a
flex-direction: columncard,align-items: flex-startgives children max-content width and defeatsbreak-wordentirely — usestretch. - Place
­at the compound boundary (Produksjons­planlegging) so the break lands in the right place, with a hyphen.
Do not use hyphens: auto for Norwegian. Chrome ships no Norwegian hyphenation patterns and produces breaks like Medlemsporta-ler and Beregningsverk-tøy. Soft hyphens are explicit and always correct.
Keep the harness out of the index
Give the page <meta name="robots" content="noindex, nofollow">. It ships on the live site and links to real pages, so it will otherwise be crawled and indexed alongside them. See Work safely on a live site.
Known artifact: the scrollbar
A 600 px frame with a classic scrollbar has a ~585 px layout viewport, so min-width: 600px rules will not apply inside it. Real phones use overlay scrollbars and do not have this offset. Treat small discrepancies at exact breakpoint values as a harness artifact and confirm on a device when it matters.
Rule of thumb
Never sign off a responsive layout from a resized window. Build an iframe harness covering every breakpoint boundary, and include one mobile-width frame tall enough to hold the entire page — that frame is the one that catches horizontal overflow, because
overflow-x: hiddenclips it without any other symptom.