Module 16 : Responsive Images & Media Objects.
1. Introduction
Why responsive images?
Bandwidth efficiency: Serving smaller images to small screens saves data.
Pixel density: High‑DPI displays (Retina) need higher resolution sources.
Art direction: Different crop/composition for narrow vs wide viewports.
Performance & UX: Faster loads, better CLS (Cumulative Layout Shift) control, better LCP (Largest Contentful Paint).
Key HTML primitives
img with srcset and sizes — responsive selection by resolution or width.
<picture> + <source> — art direction and format switching.
loading="lazy" — native lazy loading in supporting browsers.
decoding="async" — non-blocking image decoding.
Key CSS primitives
object-fit and object-position — how images fit containers.
aspect-ratio — reserve space to avoid CLS.
picture styling and img responsive max-width: img { max-width:100%; height:auto }.
Container queries (where available) for component-level responsiveness.
Formats & Compression
formats: AVIF (best compression), WebP (good support), JPEG/PNG fallback.
Use srcset to provide multiple formats: <source type="image/avif" srcset=...>.
Choose quality settings per breakpoint—avoid over‑compressing small images.
Accessibility & semantics
Always provide meaningful alt text.
For decorative images use alt="" and role="presentation" if appropriate.
Captioning and transcripts for media (video/audio).
Consider picture and img fallbacks for older UA.
2. Core Techniques
2.1 Basic srcset and sizes
srcset density descriptors: image-1x.jpg 1x, image-2x.jpg 2x — useful when switching by device pixel ratio.
srcset width descriptors: photo-400.jpg 400w, photo-800.jpg 800w — browser picks best candidate using sizes.
sizes tells the browser the intended display width for the image under different conditions (media queries).
Example (width descriptors):
<img
src="/images/photo-800.jpg"
srcset="/images/photo-400.jpg 400w, /images/photo-800.jpg 800w, /images/photo-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
alt="A mountain landscape"
style="width:100%; height:auto; aspect-ratio: 16/9;"
>
Explanation: sizes tells the browser the image will render at 100% viewport width under 600px, 50% under 1200px, otherwise 33% of viewport width. The UA uses this with srcset widths to pick the best source.
2.2 Art direction with <picture>
Use <picture> to serve different crops/compositions or formats depending on the viewport.
Example:
<picture>
<source media="(min-width: 900px)" srcset="/img/hero-wide.jpg">
<source media="(max-width: 899px)" srcset="/img/hero-tall.jpg">
<img src="/img/hero-fallback.jpg" alt="Showcase product" style="width:100%; height:auto;">
</picture>
Explanation: On wide screens the browser chooses hero-wide.jpg, on narrow screens hero-tall.jpg. If picture sources are unsupported, the img fallback loads.
2.3 Format switching (AVIF/WebP fallbacks)
<picture>
<source type="image/avif" srcset="/img/promo-800.avif 800w, /img/promo-1600.avif 1600w">
<source type="image/webp" srcset="/img/promo-800.webp 800w, /img/promo-1600.webp 1600w">
<img src="/img/promo-800.jpg" srcset="/img/promo-800.jpg 800w, /img/promo-1600.jpg 1600w" sizes="100vw" alt="Promo">
</picture>
Explanation: Browser picks AVIF if supported, otherwise WebP, otherwise JPEG.
2.4 Lazy loading & intersection observer
Use loading="lazy" for simple cases.
For fine control (preload before viewport) use IntersectionObserver to swap in src or srcset.
Pattern: set a small transparent placeholder or low‑quality blurred image (LQIP) in src, actual URLs in data-src/data-srcset, then load when near viewport.
2.5 Responsive video & iframes
Use a wrapper that preserves aspect-ratio (CSS aspect-ratio or the old padding hack).
Provide captions (<track kind="captions">) and accessible controls.
Example (CSS):
.video-wrap { aspect-ratio: 16/9; width:100%; }
.video-wrap iframe, .video-wrap video { width:100%; height:100%; }
3. Responsive Direction
Goal: Implement a component that:
Serves AVIF/WebP/JPEG fallbacks.
Uses a different crop for mobile vs desktop (art direction).
Uses aspect-ratio or reserved space to avoid CLS.
Uses srcset to supply multiple resolutions.
Files provided: /assets/hero-desktop.jpg, /assets/hero-mobile.jpg and same names with .webp and .avif.
Steps:
Create an HTML file and add the <picture> element with three <source>s: AVIF, WebP, JPEG.
Use media in sources to pick desktop vs mobile composition.
Add sizes and srcset width descriptors for each format.
Style the container with aspect-ratio: 3/1; on desktop and aspect-ratio: 16/9; for mobile using media queries.
Test by resizing the browser and using Lighthouse to record LCP and image bytes.
observe how art direction changes the visual composition, and how srcset reduces bytes served.
checklist:
4. Fine-grained Lazy Loading with IntersectionObserver
Implement lazy loading with a LQIP and prefetching behaviour so images load slightly before they enter viewport.
Steps:
Create an img tag with src pointing to a small blurred placeholder and data-srcset containing images.
Add a JS module that creates an IntersectionObserver with a rootMargin: '200px' to preload images ahead of view.
On intersection, set img.srcset = img.dataset.srcset and remove the placeholder class once the image fires load.
Add aria-busy toggles for assistive tech and ensure alt is set.
Sample JS (hint):
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.srcset = img.dataset.srcset;
img.onload = () => img.classList.remove('is-loading');
observer.unobserve(img);
}
});
}, { rootMargin: '200px 0px' });
document.querySelectorAll('img[data-srcset]').forEach(img => observer.observe(img));
Evaluation: Measure delayed loads vs immediate loads, check perceived performance.
5. Build Pipeline: Generating Responsive Image Sets (Node script)
Create a Node script that takes a high‑resolution master image and produces optimized variants (AVIF, WebP, JPEG) at multiple widths.
Why for coding specialists: Shows automation and reproducible pipelines used in production systems.
Tools: sharp (npm), fs/promises, optional CLI flags.
Script (example):
// save as scripts/generate-images.js
import sharp from 'sharp';
import fs from 'fs/promises';
const widths = [320, 640, 960, 1280, 1600];
const formats = [
{ ext: 'avif', opts: { quality: 60 } },
{ ext: 'webp', opts: { quality: 70 } },
{ ext: 'jpg', opts: { quality: 75 } }
];
async function generate(srcPath, outDir) {
await fs.mkdir(outDir, { recursive: true });
for (const w of widths) {
for (const f of formats) {
const outPath = `${outDir}/image-${w}.${f.ext}`;
await sharp(srcPath).resize(w).toFormat(f.ext, f.opts).toFile(outPath);
console.log('Wrote', outPath);
}
}
}
// usage: node --loader ts-node/esm scripts/generate-images.js
generate('./master.jpg', './dist').catch(err => console.error(err));
Explanation: sharp resizes and encodes into efficient formats. These outputs can be uploaded to a CDN. The script is a starting point — production systems add caching, incremental builds, and concurrency.
6. Performance Measurement & Research
Metrics to measure
LCP (Largest Contentful Paint) — often affected by hero images.
CLS (Cumulative Layout Shift) — use aspect-ratio or reserved space.
Total Page Weight and Image Bytes.
TTI (Time to Interactive) and First Contentful Paint (FCP).
Research directions
Comparative compression efficiency: AVIF vs WebP vs JPEG — test datasets.
Impact of lazy loading on LCP and CLS for long pages.
Art direction strategies and UX on cropping and composition.
CDN edge resizing vs build-time resizing (pr)
No comments:
Post a Comment