HTML Img Attributes Table
| Attribute | What it does | Field note |
|---|---|---|
srcset (w) | img-800.jpg 800w, img-1600.jpg 1600w | A menu - the browser picks by viewport and DPR, not by your guess |
sizes | How wide the slot renders | Without it the browser assumes 100vw and over-downloads - the pair with srcset |
srcset (x) | photo.jpg 1x, [email protected] 2x | Fixed-size images only - the wrong tool for fluid layouts |
loading="lazy" | Defer offscreen downloads | Never on the LCP hero - lazy LCP is a self-inflicted Core Web Vitals regression |
decoding="async" | Decode off the main thread | Removes the decode jank frame on large images |
width + height | Intrinsic ratio before load | Reserves the box - THE layout-shift fix, zero JavaScript |
alt | The accessibility contract | Decorative images get alt="" - the attribute must exist; its emptiness is the statement |
picture + source | Format switch / art direction | type= for WebP/AVIF fallback; media= for different crops per breakpoint |
Responsive images are a negotiation, not a media query exercise: srcset hands the browser a menu of files, sizes tells it how wide the slot renders, and the BROWSER picks - it knows the viewport width and device pixel ratio; it cannot know your CSS. That division of labor is the whole design.
Bottom line: width and height attributes kill layout shift before it exists - the browser reserves the box from the ratio before a byte arrives, zero JavaScript. loading=lazy everything EXCEPT the hero: deferring the LCP image is a self-inflicted Core Web Vitals regression. Decoration is alt='' - the attribute present but empty is the statement.
The honest part: x-descriptors (2x, 3x) only fit fixed-size images. For fluid layouts they mislead the browser into over- or under-downloading; w-descriptors with sizes are the default answer. picture/source is the specialist tool - format switching (WebP/AVIF with fallback) and art direction (different crops per breakpoint), not everyday responsiveness.
How to use
- Write the fluid default: srcset with w-descriptors plus a sizes attribute that matches the real layout slot - img-800.jpg 800w, img-1600.jpg 1600w with sizes=(max-width: 700px) 100vw, 50vw.
- Reserve space: always author width and height attributes - CSS scales them (height: auto), and the aspect-ratio box eliminates layout shift on slow connections.
- Tier the loading: hero image eager with fetchpriority=high, everything below the fold loading=lazy decoding=async - the browser skips what nobody scrolled to.
Frequently asked questions
What is the difference between the x and w descriptors in srcset?
x-descriptors state device pixel ratio: [email protected] 2x means 'give 2x screens this file'. That only computes when the image renders at a FIXED css size - the browser can solve pixels per ratio. w-descriptors state the file's real pixel width (img-800.jpg 800w), and the browser combines them with the sizes attribute (how wide the slot is) to pick the smallest file that still looks sharp at any viewport. Fluid layouts need w-descriptors because the slot width varies; x-descriptors on a fluid image make the browser guess with wrong assumptions and over-download on phones.
Why does loading=lazy on my hero image make LCP worse?
Lazy defers the download until the browser is confident the image is near the viewport, and that confidence check runs at low priority - exactly the opposite of what the Largest Contentful Paint element needs. The hero is almost always the LCP element; deferring it moves the paint later, sometimes by whole seconds on fast devices. The correct pattern: hero eager, decoding=async, fetchpriority=high, preloaded via a link rel=preload when it is truly first paint; lazy belongs to below-the-fold content images.
Do width and height attributes still matter with CSS sizing?
Yes - more than ever, and for a different reason than in the 1990s. The browser reads the two integers, computes the aspect ratio, and reserves the box BEFORE the image data arrives; your CSS (width: 100%; height: auto) then scales the box responsively. Delete the attributes and the box collapses to zero until download completes, shoving the entire page downward on slow connections - the classic layout-shift cliff. The attributes are metadata for layout, not presentation, which is why they survive full CSS control of the final size.
When do I need picture and source instead of plain img srcset?
For the two jobs srcset cannot do. Format switching: <source type=image/webp> lets the browser take WebP or AVIF when it can and fall back to JPEG - a plain srcset cannot switch formats, only sizes. Art direction: <source media=(max-width: 600px)> can serve a tightly-cropped square on phones and the wide original on desktop - different COMPOSITIONS, not just different resolutions. Everyday same-crop responsiveness stays on srcset+sizes; picture is the escalation when format savings or per-breakpoint crops are worth the extra markup.