Sheath rule
perf-responsive-images
Images should use
srcset for responsive loading.
- Package
- Core
- Category
- Performance
- Default severity
- info by default
- Auto-fix
- Manual fix
#Why
A single src sends every visitor the same file. Sized for a desktop hero, a
phone on a mobile connection downloads several times the pixels it can display;
sized for the phone, a high-density screen renders it soft.
srcset lets the browser pick, using the viewport and pixel density it alone
knows at request time.
#Examples
#Bad
<!-- Single image for all devices: a phone on a mobile connection downloads the 1920px file for a 320px viewport -->
<img src="/images/hero-1920.jpg" alt="Hero Image" width="800" height="600">
#Good
<!-- Responsive with srcset (width descriptors) -->
<img src="/images/hero-800.jpg"
srcset="/images/hero-400.jpg 400w,
/images/hero-800.jpg 800w,
/images/hero-1200.jpg 1200w,
/images/hero-1920.jpg 1920w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
800px"
alt="Hero Image">
<!-- Retina with srcset (pixel density descriptors) -->
<img src="/images/logo.png"
srcset="/images/logo.png 1x,
/images/logo@2x.png 2x,
/images/logo@3x.png 3x"
alt="Logo">
<!-- SVG images don't need srcset -->
<img src="/images/icon.svg" alt="Icon">
<!-- Decorative images are skipped -->
<img src="/images/decoration.jpg" alt="">
#srcset Syntax
#Width Descriptors (w)
srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1600w"
Browser selects based on viewport width and pixel density.
#Pixel Density Descriptors (x)
srcset="normal.jpg 1x, retina.jpg 2x, super-retina.jpg 3x"
Browser selects based on device pixel ratio.
#sizes Attribute
Tells the browser how large the image will display:
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
800px"
Meaning:
- Below 600px viewport: image is 100% of viewport width
- Below 1200px viewport: image is 50% of viewport width
- Above 1200px: image is 800px wide
#Options
Use these options to set the minimum checked width and exclude selected URLs.
| Option | Type | Default | Description |
|---|---|---|---|
minWidth |
int | 300 |
Skip images smaller than this |
excludePatterns |
array | [] |
URL patterns to exclude |
excludeClasses |
array | ['icon', 'favicon', 'logo-small', 'badge', 'avatar-sm'] |
Exact, case-insensitive class tokens to exclude |
<?php
'perf-responsive-images' => ['warning', [
'minWidth' => 400,
'excludePatterns' => ['icons/', 'logos/'],
'excludeClasses' => ['thumbnail', 'product-swatch'],
]],
Each list replaces its default. Set excludeClasses to [] to evaluate images
regardless of their CSS classes.
#What's Skipped
- Images with at least one valid static
srcsetcandidate, or a dynamicsrcsetwhose runtime value cannot be determined - SVG images (vector, resolution-independent)
- Data URIs
- Small images (below
minWidth) - Images whose class list contains an
excludeClassestoken - Decorative images (
role="presentation"or emptyalt)
#Notes
- Use width descriptors (
w) for most responsive images - Use pixel density descriptors (
x) for fixed-size images like logos - Width, height, and density descriptors must be positive; duplicate or mixed width/density descriptors do not form a usable candidate
- Consider
<picture>for art direction (different crops per viewport) - Missing
srcsetis not reported when image attributes are generated dynamically, such as with{{ $attributes }}or@if
#References
- web.dev: Serve Responsive Images - Complete guide to responsive image techniques
- MDN: srcset Attribute - Documentation on the srcset attribute
#Related Rules
- perf-require-explicit-size - Prevent layout shift
- perf-lazy-load-images - Defer offscreen images