The <img> element
The <img> element embeds a raster or vector image into a document.
It is a void element (no closing tag) and a replaced element —
meaning the browser replaces the element's layout box with external content (the image file) rather than
rendering child nodes. Because the content comes from outside the document, the browser needs
guidance from you about what it shows and how much space to reserve for it.
At minimum, every <img> needs a src and an alt
attribute. Everything else is either optional or can be handled by CSS, but those two
are always required.
The alt attribute
alt is not optional — it is required on every <img>.
Its value is the text alternative for the image, used by:
- Screen readers, which read the alt text aloud to blind or low-vision users
- Browsers, which display it when the image fails to load
- Search engines, which index it to understand the image's content
Write alt text that conveys the meaning of the image in its context — not a
generic description like "photo" or "image." If an image is purely decorative and adds
no information, use an empty string (alt="") so assistive technology skips
it entirely. A missing alt attribute is different from an empty one: a
missing attribute may cause a screen reader to read out the filename, which is useless.
Demo: basic <img>
width/height and layout stability
Always include width and height attributes matching the
image's intrinsic dimensions — the actual pixel size of the file.
For product-800.jpg above, that is 800 pixels wide and 533 pixels tall
(a 3:2 aspect ratio).
The browser uses these values to calculate the image's aspect ratio before the file has finished downloading. This lets it reserve the exact right amount of vertical space in the layout early, preventing a jarring jump when the image finally appears — a phenomenon measured by the Core Web Vital called Cumulative Layout Shift (CLS). High CLS hurts both user experience and search ranking.
Attributes set the intrinsic ratio; CSS controls the rendered size
An important distinction: width and height attributes on
<img> are used to derive the aspect ratio the
browser uses to reserve space. They are not a hard constraint on the
rendered size.
If you add max-width: 100%; height: auto in CSS (a common responsive
pattern already applied in this tutorial's stylesheet), the CSS overrides the
attribute dimensions — the image shrinks to fit its container. The browser still
uses the attribute values to compute the correct aspect ratio for the reserved box,
so there is no layout shift even though the rendered width has changed.
If you set an explicit CSS width on an image, that value wins over the
attribute. The attributes then serve only as the aspect-ratio source for the box.
This is by design: attributes describe the file; CSS describes the presentation.
Demo: the same image at attribute size vs CSS-constrained size
Both images below reference the same 800×533 file with the same
width="800" height="533" attributes. The second is also given a CSS
style="max-width:300px; height:auto" — the CSS wins for the rendered
size, but the 3:2 ratio is still correctly derived from the attributes.
The decoding attribute
By default, the browser decodes an image on the main thread — the same thread responsible for running JavaScript and painting pixels to screen. A large or complex image can therefore block rendering briefly while it is being decoded.
Setting decoding="async" tells the browser it may decode the image
off the main thread, deferring the decode work to a background
thread. The rest of the page can continue painting while the image is processed
in the background, which can make the page feel more responsive.
When to use decoding="async"
Use it on any image that is not part of the first visible render — product thumbnails,
gallery images, images below the fold, and any image loaded by JavaScript. The key
rule: do not put decoding="async" on a hero image. The
hero is usually your page's Largest Contentful Paint element; async decoding can
actually delay it arriving on screen.
The default value is auto, which lets the browser decide. In practice
most browsers treat auto similarly to sync for small images
and may apply background decoding for large ones — but being explicit about
async for non-critical images removes the guesswork.
Hero (no decoding attribute):
Below-fold content image (decoding="async"):
<figure> and <figcaption>
When an image needs a visible caption — one that is part of the document's content
rather than a tooltip — wrap it in a <figure> element and add a
<figcaption>. This creates an explicit semantic association between
the image and its caption that both browsers and screen readers understand.
The caption can expand on what the alt text states, add attribution, or give context that all readers benefit from — not just those using assistive technology.
A useful rule of thumb: alt is the fallback for when the image is absent;
<figcaption> is visible supplementary information for all readers.
If the caption fully describes the image, the alt text can be an empty string
(alt="") — you do not need to repeat identical text in both places.
The <figure> element is not only for images
<figure> is a generic container for self-contained content — anything
that could be extracted from the main flow and placed in an appendix or sidebar without
disrupting the surrounding text. Code listings, charts, audio clips, and tables can all
be wrapped in <figure> when they have a caption. For images,
however, it is by far the most common use.