docs(perf): update image best practices and TTFB thresholds based on feedback

- Add width/height to <source> elements for correct aspect-ratio in art direction.
- Use realistic 'sizes' attributes in hero image examples.
- Remove 'decoding=sync' from hero images to avoid blocking the main thread.
- Align TTFB 'good' threshold with web.dev standards (800ms).
This commit is contained in:
Joan Leon committed 2026-04-08 11:24:16 +02:00
1 parent 7a9887cedb
commit 22df069c40
2 files changed
+17 -9

No files matched your search

+3 -3
View File
@@ -20,7 +20,7 @@ Quick reference checklist for web application performance. Use alongside the `pe
## TTFB Diagnosis
When TTFB is slow (> 600ms), check each component in DevTools Network waterfall:
When TTFB is slow (> 800ms), check each component in DevTools Network waterfall:
- [ ] **DNS resolution** slow → add `<link rel="dns-prefetch">` or `<link rel="preconnect">` for known origins
- [ ] **TCP/TLS handshake** slow → enable HTTP/2, consider edge deployment, verify keep-alive
@@ -31,9 +31,9 @@ When TTFB is slow (> 600ms), check each component in DevTools Network waterfall:
### Images
- [ ] Images use modern formats (WebP, AVIF)
- [ ] Images are responsively sized (`srcset` and `sizes`)
- [ ] Images have explicit `width` and `height` attributes and/or CSS `aspect-ratio` (prevents CLS)
- [ ] Images and `<source>` elements have explicit `width` and `height` (prevents CLS in art direction)
- [ ] Below-the-fold images use `loading="lazy"` and `decoding="async"`
- [ ] Hero/LCP images use `fetchpriority="high"`, `decoding="sync"`, and no lazy loading
- [ ] Hero/LCP images use `fetchpriority="high"` and no lazy loading
### JavaScript
- [ ] Bundle size under 200KB gzipped (initial load)
+14 -6
View File
@@ -162,35 +162,43 @@ const tasks = await db.tasks.findMany({
- Resolution switching (srcset + sizes): right file size per screen density
-->
<picture>
<!-- Mobile: portrait crop -->
<!-- Mobile: portrait crop (8:10) -->
<source
media="(max-width: 767px)"
srcset="/hero-mobile-400.avif 400w, /hero-mobile-800.avif 800w"
sizes="100vw"
width="800"
height="1000"
type="image/avif"
/>
<source
media="(max-width: 767px)"
srcset="/hero-mobile-400.webp 400w, /hero-mobile-800.webp 800w"
sizes="100vw"
width="800"
height="1000"
type="image/webp"
/>
<!-- Desktop: landscape crop -->
<!-- Desktop: landscape crop (2:1) -->
<source
srcset="/hero-800.avif 800w, /hero-1200.avif 1200w, /hero-1600.avif 1600w"
sizes="100vw"
sizes="(max-width: 1200px) 100vw, 1200px"
width="1200"
height="600"
type="image/avif"
/>
<source
srcset="/hero-800.webp 800w, /hero-1200.webp 1200w, /hero-1600.webp 1600w"
sizes="100vw"
sizes="(max-width: 1200px) 100vw, 1200px"
width="1200"
height="600"
type="image/webp"
/>
<img
src="/hero-desktop.jpg"
style="aspect-ratio: 1200 / 600"
width="1200"
height="600"
fetchpriority="high"
decoding="sync"
alt="Hero image description"
/>
</picture>