vibecheck0.3.0
Performanceunoptimized-imageserror

Unoptimized images in Svelte

Images are usually the heaviest thing on a page, and when they ship without width/height they shift the layout as they load, when they ship at 2400px in a 400px slot they waste most of what they download, and when they load eagerly below the fold they steal bandwidth from what’s actually visible. AI scaffolds paste raw <img src> tags with none of the attributes that make images fast.

Symptoms

  • Layout jumps as each image loads (no reserved space)
  • A tiny thumbnail downloads a multi-megapixel original
  • Below-the-fold images load immediately, delaying the hero
  • Images look slightly stretched or squished (wrong declared ratio)

How VibeCheck catches it

In your widget · Problems

errorunoptimized-imageshero.png (2400×1200) missing width/height

To your coding agent · MCP

agent › get_detected_issues
{ detector: "unoptimized-images", issue: "hero.png (2400×1200) missing width/height", threshold: "Natural size > 2× rendered size, or declared aspect ratio off by > 0.15, or missing dimensions/lazy/alt" }

The same string in your widget and in your agent’s context — no screenshot, no copy-paste.

Root causes

  • No width/height attributes, so the browser can’t reserve space
  • The source image is far larger than the size it’s displayed at
  • No loading="lazy" on images below the fold
  • Declared width/height that don’t match the file’s real aspect ratio

The fix for Svelte

@sveltejs/enhanced-img processes local images at build time — generating dimensions, modern formats, and a srcset from a single <enhanced:img> tag.

svelte
<script>
  import hero from '$lib/hero.jpg?enhanced'
</script>

<enhanced:img src={hero} alt="Product dashboard" />

Svelte docs →

Steps

  1. Add width and height attributes matching the file’s real aspect ratio
  2. Add loading="lazy" to images below the fold (never to the LCP image)
  3. Resize and re-encode to WebP/AVIF at the displayed size, with srcset for density

See the general, framework-agnostic fix →

FAQ

Should I lazy-load every image?
No — never lazy-load your LCP (largest, above-the-fold) image; that delays the most important paint. Lazy-load only images below the fold. In Next.js, mark the hero with priority.
What does "oversized" mean exactly?
VibeCheck flags an image whose natural (file) dimensions are more than twice its rendered (displayed) size — you’re downloading at least 4× the pixels you show. Resize to the displayed size, 2× for retina.
Why does missing width/height cause layout shift?
Without dimensions the browser doesn’t know the image’s size until it downloads, so it reserves no space and everything below jumps when the image arrives. The attributes let it reserve the box up front.