Images

Add an image that is accessible, correctly sized and does not shift the page as it loads.

07of 22
≈ 11Min read
8Parts

src and alt

src is the file. alt is what the image says — not what it looks like. Write the sentence you would use if you were reading the page aloud over the phone to someone who cannot see the screen.

a complete img
<img src="/media/lever.jpg"
     alt="A brass door lever on a walnut door"
     width="1600" height="900"
     loading="lazy" decoding="async">

Deciding what alt should say

The image is…alt should be
Carrying informationThe information. "A brass lever on a walnut door".
Inside a link or buttonThe destination or action, not the picture.
Repeating the caption next to italt="" — do not say it twice.
Pure decorationalt="" — empty, present, deliberate.
A chart or diagramA short summary, with the detail in real text nearby.
Text as a pictureThe exact words in the image.
Empty is not the same as missing

A missing alt makes many screen readers read the file name — "I M G underscore four two nine dot J P G". An empty alt tells them to skip the image entirely. Never leave it out.

Formats

FormatBest forNotes
SVGLogos, icons, diagramsVector — sharp at any size, tiny, styleable with CSS.
AVIFPhotographsSmallest of the photographic formats; slower to encode.
WebPPhotographs, screenshotsWell supported, much smaller than JPEG.
JPEGPhotographsThe universal fallback.
PNGScreenshots, transparency, flat colourLossless and therefore large for photos.
GIFNothing, nowUse a short muted video instead — it is far smaller.

Why width and height still matter

Giving the intrinsic size lets the browser reserve the right space before the file arrives, so text does not jump down the page while images load. That jump is Cumulative Layout Shift, and it is one of the metrics Google measures.

The attributes only supply the aspect ratio. CSS still decides the size it is drawn at — so pair them with width: 100%; height: auto.

the pairing that always works
img {
  max-width: 100%;
  height: auto;   /* keeps the ratio from the attributes */
}

Loading and decoding

  • loading="lazy" defers images that are off screen. Never put it on the image at the top of the page — that one is needed immediately, and lazy loading it delays the largest paint.
  • decoding="async" lets the browser decode off the main thread, so a large image does not stall interaction.
  • fetchpriority="high" on the single most important image tells the browser to go first.

Fitting a box

When the image and its box have different shapes, object-fit decides what happens. cover fills and crops, contain fits and letterboxes. object-position moves the crop.

a fixed-ratio thumbnail
.thumb {
  aspect-ratio: 16 / 9;
  width: 100%;
  object-fit: cover;
  object-position: 50% 35%;   /* keep the faces in frame */
}

figure and figcaption

When an image needs a visible caption, wrap them together. The caption and the alt do different jobs: the caption is read by everyone, the alt replaces the image for someone who cannot see it. They should not be the same sentence.

image with a caption
<figure>
  <img src="/media/hall.jpg" alt="A corridor with no visible door frames" width="1600" height="900">
  <figcaption>Park Hill Tower, 2025. Six doors are in this photograph.</figcaption>
</figure>

SVG in the page

An SVG can be used as a file in <img>, or pasted inline. Inline SVG can be styled and animated with CSS and can inherit currentColor; as an <img> it is cached like any other file and cannot be styled.

For an icon inside a labelled button, mark the SVG aria-hidden="true" so it is not announced twice.

Practice