Cumulative layout shift (CLS) in Vanilla JS
Layout shift is when content jumps after it has already rendered — an image loads and pushes the text down, a banner injects itself above the fold, a web font swaps and reflows everything. It is a Core Web Vitals metric Google ranks on, and it makes users tap the wrong thing. AI-built pages shift constantly because generated markup omits width/height on images and drops late content in without reserving space.
Framework fixes
Symptoms
How VibeCheck catches it
In your widget · Problems
Layout shift cluster detected (3 shifts)
To your coding agent · MCP
agent › get_detected_issues
→ { detector: "layout-thrashing", issue: "Layout shift cluster detected (3 shifts)", threshold: "≥ 3 layout shifts within a 500ms window, with no recent user input" }
The same string in your widget and in your agent’s context — no screenshot, no copy-paste.
Root causes
The fix for Vanilla JS
Set the width and height attributes on media, and wrap embeds in an aspect-ratio box. Never document.body.prepend() content above what the user is already reading.
<img src="/hero.jpg" width="1200" height="630" alt="Hero" style="width:100%;height:auto" />Steps
- Add
widthandheight(oraspect-ratio) to every image, video, and iframe - Reserve a fixed-size slot for anything injected after load (ads, banners, embeds)
- Use
font-display: optionalor a size-adjusted fallback to avoid font-swap reflow
FAQ
- What CLS score do I need?
- Google considers CLS good at 0.1 or below, and poor above 0.25, for 75% of page loads. It is one of the three Core Web Vitals used in ranking.
- Why does the layout-thrashing detector flag this?
- VibeCheck observes the browser’s layout-shift entries. When three or more fire within 500ms without user input, it flags a cluster — that burst is exactly what a jumpy load feels like.
- My image is responsive — do I still set
widthandheight? - Yes. Set the intrinsic
width/heightattributes so the browser knows the aspect ratio, then use CSS (width:100%;height:auto) to scale it. That gives you responsiveness with zero shift.