Sheath rule
perf-require-explicit-size
Images should have explicit
width and height attributes.
- Package
- Core
- Category
- Performance
- Default severity
- warning by default
- Auto-fix
- Manual fix
#Why
An <img> with no dimensions occupies no space until it loads, so the browser
lays the page out without it and lays it out again once it arrives. Whatever the
reader was looking at moves, which is what Cumulative Layout Shift measures.
width and height give the browser the aspect ratio up front, so the space is
reserved before the bytes arrive. CSS can still size the image; the attributes
are there for the ratio, not the final dimensions.
#Examples
#Bad
<!-- Missing dimensions -->
<img src="/images/photo.jpg" alt="Photo">
<!-- Missing width -->
<img src="/images/photo.jpg" alt="Photo" height="400">
<!-- Missing height -->
<img src="/images/photo.jpg" alt="Photo" width="600">
<!-- Present but not a valid intrinsic dimension -->
<img src="/images/photo.jpg" alt="Photo" width="600px" height="auto">
#Good
<!-- Both dimensions specified -->
<img src="/images/photo.jpg" alt="Photo" width="600" height="400">
<!-- With CSS for responsive sizing -->
<img src="/images/photo.jpg" alt="Photo" width="600" height="400"
style="max-width: 100%; height: auto;">
<!-- Using aspect-ratio CSS (modern approach) -->
<img src="/images/photo.jpg" alt="Photo" width="600" height="400"
class="responsive-image">
.responsive-image {
width: 100%;
height: auto;
aspect-ratio: 600 / 400;
}
#How It Prevents Layout Shift
Without dimensions:
[Loading...] → [████████████]
↑ Text below shifts down
With dimensions:
[░░░░░░░░░░░░] → [████████████]
↑ Space reserved ↑ No shift
#Modern CSS Approach
Browsers now calculate aspect ratio from width and height:
<!-- Set intrinsic dimensions -->
<img src="image.jpg" width="800" height="600" alt="Photo">
/* Make responsive while preserving ratio */
img {
max-width: 100%;
height: auto;
}
The browser computes the aspect ratio (800/600 = 4:3) and reserves space.
#What's Skipped
- SVG images: Often use
viewBoxfor sizing instead, including SVG URLs with a query string or fragment - Dynamic source values: The rule cannot determine whether the runtime image is an SVG
- Dynamic dimensions: Blade/bound values are left for runtime validation
#Common Dimensions
Preserve the source asset's aspect ratio when setting explicit dimensions.
| Content Type | Typical Ratio | Example |
|---|---|---|
| Photos | 4:3, 3:2, 16:9 | 800x600, 1200x800 |
| Thumbnails | 1:1, 4:3 | 150x150, 200x150 |
| Hero images | 16:9, 21:9 | 1920x1080, 2560x1080 |
| Avatars | 1:1 | 48x48, 96x96 |
#Notes
- Static values must be non-negative integers such as
width="600"; HTML intrinsic dimension attributes do not acceptpx,auto, percentages, or negative values - Dynamic Blade dimension values are left for runtime
widthandheightset the intrinsic size; CSS controls the display size- This is especially important for lazy-loaded images
- Missing dimensions are not reported when image attributes are generated dynamically, such as with
{{ $attributes }}or@if
#References
- web.dev: Cumulative Layout Shift (CLS) - Understanding CLS and how to prevent it
- MDN: Image width and height - Documentation on image dimension attributes
#Related Rules
- perf-lazy-load-images - Defer image loading
- perf-responsive-images - Responsive image sizes
- a11y-alt-text - Images need alt text