HTML Img Attributes Table

AttributeWhat it doesField note
srcset (w)img-800.jpg 800w, img-1600.jpg 1600wA menu - the browser picks by viewport and DPR, not by your guess
sizesHow wide the slot rendersWithout it the browser assumes 100vw and over-downloads - the pair with srcset
srcset (x)photo.jpg 1x, [email protected] 2xFixed-size images only - the wrong tool for fluid layouts
loading="lazy"Defer offscreen downloadsNever on the LCP hero - lazy LCP is a self-inflicted Core Web Vitals regression
decoding="async"Decode off the main threadRemoves the decode jank frame on large images
width + heightIntrinsic ratio before loadReserves the box - THE layout-shift fix, zero JavaScript
altThe accessibility contractDecorative images get alt="" - the attribute must exist; its emptiness is the statement
picture + sourceFormat switch / art directiontype= for WebP/AVIF fallback; media= for different crops per breakpoint
Reference: the MDN img element reference. The img attributes are a negotiation with the browser: srcset hands it a menu, sizes tells it how wide the plate is, and the BROWSER picks - it knows the viewport and device pixel ratio; it cannot know your CSS. That is why w-descriptors with sizes beat x-descriptors for fluid layouts. Bottom line: width and height attributes kill layout shift before it exists (the box is reserved from the ratio), loading=lazy everything EXCEPT the hero (deferring the LCP image delays the LCP), and decoration is alt="" - present but empty. Related tools: backgrounds table (when CSS paint beats an img element), meta tags table (og:image is a different delivery), and HTTP caching table (the second download is free or not, per headers).

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

  1. 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.
  2. Reserve space: always author width and height attributes - CSS scales them (height: auto), and the aspect-ratio box eliminates layout shift on slow connections.
  3. 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.

Related tools