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.
<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 information | The information. "A brass lever on a walnut door". |
| Inside a link or button | The destination or action, not the picture. |
| Repeating the caption next to it | alt="" — do not say it twice. |
| Pure decoration | alt="" — empty, present, deliberate. |
| A chart or diagram | A short summary, with the detail in real text nearby. |
| Text as a picture | The exact words in the image. |
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
| Format | Best for | Notes |
|---|---|---|
SVG | Logos, icons, diagrams | Vector — sharp at any size, tiny, styleable with CSS. |
AVIF | Photographs | Smallest of the photographic formats; slower to encode. |
WebP | Photographs, screenshots | Well supported, much smaller than JPEG. |
JPEG | Photographs | The universal fallback. |
PNG | Screenshots, transparency, flat colour | Lossless and therefore large for photos. |
GIF | Nothing, now | Use 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.
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.
.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.
<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.