performance/responsive-image · Responsive image
Large images should provide a srcset.
Severity: info
What it checks
Flags an <img> without a srcset attribute. An <img> that is the fallback of a <picture> whose <source> elements carry a srcset is not flagged: the browser picks from those candidates.
An SVG is not flagged, since a vector image scales to any size from one file. That covers a src path ending in .svg (query and fragment ignored), an inline data:image/svg+xml URI, and in source analysis an src={logo} whose logo is imported from a .svg file, or a call given a .svg path as a string literal (src={asset('/icons/x.svg')}).
Why it matters
An <img> without srcset ships one fixed-size asset to every device, wasting bytes on small screens. Static analysis cannot measure the intended display size, so this is advisory.
How to fix
Add a srcset (and sizes) so the browser can pick a right-sized image:
<img
src="/hero.jpg"
srcset="/hero-800.jpg 800w, /hero-1600.jpg 1600w"
sizes="100vw"
width="1600"
height="900"
alt="…"
/>
Mode differences
Source analysis (the CLI, the dashboard’s static baseline) reads the <img> elements in the route’s own templates, meaning the page and its layout chain, not those rendered by a child component. An attribute counts as present when it is written, whatever its value, and a spread ({...rest}) counts as present for every attribute. Rendered analysis (the Vite plugin’s build pass, a route you visit in the dashboard) reads every <img> in the shipped body; the build pass covers prerendered routes only, and its findings anchor to the HTML file with no source line, so an inline svelte-vitals-disable-next-line reaches only the source-analysis finding. When the two disagree, trust the rendered result.
Disabling
Record existing findings in the suppressions file (npx svelte-vitals --update-suppressions), scope the rule per route or path with overrides, or turn it off:
export default {
rules: {
'performance/responsive-image': 'off'
}
};